Esempio n. 1
0
 public static KeyboardInput CreateFrom(WinAPI.WM wParam, Mubox.WinAPI.WindowHook.KBDLLHOOKSTRUCT hookStruct)
 {
     KeyboardInput e = new KeyboardInput();
     e.VK = hookStruct.vkCode;
     e.Scan = hookStruct.scanCode;
     e.Flags = hookStruct.flags;
     e.Time = hookStruct.time;
     e.WM = wParam;
     return e;
 }
Esempio n. 2
0
        public static KeyboardInput CreateFrom(Win32.WM wParam, Mubox.Win32.WindowHook.KBDLLHOOKSTRUCT hookStruct)
        {
            KeyboardInput e = new KeyboardInput();

            e.VK    = hookStruct.vkCode;
            e.Scan  = hookStruct.scanCode;
            e.Flags = hookStruct.flags;
            e.Time  = hookStruct.time;
            e.WM    = wParam;
            return(e);
        }
Esempio n. 3
0
 private static void OnKeyboardInputReceivedInternal(KeyboardInput e)
 {
     try
     {
         if (e != null)
         {
             KeyboardInputReceived(null, e);
             if (Performance.IsPerformanceEnabled)
             {
                 KeyboardHandlerPerformance.Count((long)(e.CreatedTime - DateTime.Now).TotalMilliseconds);
             }
         }
     }
     catch (Exception ex)
     {
         ex.Log();
     }
 }
Esempio n. 4
0
 public virtual void Dispatch(KeyboardInput e)
 {
 }
Esempio n. 5
0
        private void Process(KeyboardInput keyboardInput)
        {
            if (!UpdatePressedKeys(keyboardInput.VK, keyboardInput.Scan, keyboardInput.Flags, keyboardInput.Time))
            {
                return;
            }

            switch ((WinAPI.VK)keyboardInput.VK)
            {
                case WinAPI.VK.Control:
                case WinAPI.VK.LeftControl:
                case WinAPI.VK.RightControl:
                    if ((keyboardInput.Flags & WinAPI.WindowHook.LLKHF.UP) == WinAPI.WindowHook.LLKHF.UP)
                    {
                        CurrentMK = (CurrentMK | WinAPI.Windows.MK.MK_CONTROL) ^ WinAPI.Windows.MK.MK_CONTROL;
                    }
                    else
                    {
                        CurrentMK |= WinAPI.Windows.MK.MK_CONTROL;
                    }
                    break;

                case WinAPI.VK.Shift:
                case WinAPI.VK.LeftShift:
                case WinAPI.VK.RightShift:
                    if ((keyboardInput.Flags & WinAPI.WindowHook.LLKHF.UP) == WinAPI.WindowHook.LLKHF.UP)
                    {
                        CurrentMK = (CurrentMK | WinAPI.Windows.MK.MK_SHIFT) ^ WinAPI.Windows.MK.MK_SHIFT;
                    }
                    else
                    {
                        CurrentMK |= WinAPI.Windows.MK.MK_CONTROL;
                    }
                    break;
            }

            var vk = keyboardInput.VK;
            var flags = keyboardInput.Flags;
            var scan = keyboardInput.Scan;
            var time = keyboardInput.Time;
            var cas = keyboardInput.CAS;

            var wParam = (uint)vk;

            WinAPI.WM wm = (((flags & WinAPI.WindowHook.LLKHF.UP) == WinAPI.WindowHook.LLKHF.UP) ? WinAPI.WM.KEYUP : WinAPI.WM.KEYDOWN); // TODO SYSKEYDOWN via Win32.WindowHook.LLKHF.AltKey ?
            uint lParam = 0x01;

            if (wm == WinAPI.WM.KEYUP)
            {
                lParam |= 0xC0000000; // TODO: this may need to change on 64bit platforms, not clear
            }

            uint scanCode = scan;
            if (scanCode > 0)
            {
                lParam |= ((scanCode & 0xFF) << 16); // TODO: this may need to change on 64bit platforms, not clear
            }

            if ((flags & WinAPI.WindowHook.LLKHF.UP) != WinAPI.WindowHook.LLKHF.UP)
            {
                // async Win32.GetKeyboardState or similar to capture actual/current CAS states
                if ((cas & WinAPI.CAS.CONTROL) != 0)
                {
                    Process(new KeyboardInput
                    {
                        VK = WinAPI.VK.Control,
                        Flags = (WinAPI.WindowHook.LLKHF)0,
                        Scan = (uint)WinAPI.SendInputApi.MapVirtualKey(WinAPI.VK.Control, WinAPI.SendInputApi.MAPVK.MAPVK_VK_TO_VSC),
                        Time = time,
                        CAS = (WinAPI.CAS)0,
                    });
                }
                if ((cas & WinAPI.CAS.ALT) != 0)
                {
                    Process(new KeyboardInput
                    {
                        VK = WinAPI.VK.Menu,
                        Flags = (WinAPI.WindowHook.LLKHF)0,
                        Scan = (uint)WinAPI.SendInputApi.MapVirtualKey(WinAPI.VK.Menu, WinAPI.SendInputApi.MAPVK.MAPVK_VK_TO_VSC),
                        Time = time,
                        CAS = (WinAPI.CAS)0,
                    });
                    flags |= WinAPI.WindowHook.LLKHF.ALTDOWN;
                }
                if ((cas & WinAPI.CAS.SHIFT) != 0)
                {
                    Process(new KeyboardInput
                    {
                        VK = WinAPI.VK.Shift,
                        Flags = (WinAPI.WindowHook.LLKHF)0,
                        Scan = (uint)WinAPI.SendInputApi.MapVirtualKey(WinAPI.VK.Shift, WinAPI.SendInputApi.MAPVK.MAPVK_VK_TO_VSC),
                        Time = time,
                        CAS = (WinAPI.CAS)0,
                    });
                }
            }

            // NOTE: some apps may actually rely on keyboard state, AttachInputThread will clobber keyboard state. now that we don't continually attach/detach we should be able to set keyboard correctly
            // TODO: this should be a game profile level option - some games exhibit 'double entry' of input when this is called
            WinAPI.SetKeyboardState(this.pressedKeys);
            /* REMOVED: key state becomes invalid for at least one game with this implemented - need to put it into an option if it needs to be re-added - was never noticed because for a while LeftMenu was not being translated into 'Menu' and this code was not executing
            if (this.pressedKeys[(int)WinAPI.VK.Menu] == 0x80 || keyboardInput.VK == WinAPI.VK.Menu)
            {
                switch (wm)
                {
                    case WinAPI.WM.KEYDOWN:
                        wm = WinAPI.WM.SYSKEYDOWN;
                        break;

                    case WinAPI.WM.KEYUP:
                        wm = WinAPI.WM.SYSKEYUP;
                        break;
                }
            }
            else
            {
                switch (wm)
                {
                    case WinAPI.WM.SYSKEYDOWN:
                        wm = WinAPI.WM.KEYDOWN;
                        break;

                    case WinAPI.WM.SYSKEYUP:
                        wm = WinAPI.WM.KEYUP;
                        break;
                }
            }
            */
            WinAPI.Windows.SendMessage(ClientWindowHandle, wm, new UIntPtr(wParam), new UIntPtr(lParam));

            // if keydown, translate message
            // TODO: this should be a game profile option - some games may exhibit 'double entry' of input when this is called, most games don't function correctly without it
            if (wm == WinAPI.WM.KEYDOWN || wm == WinAPI.WM.SYSKEYDOWN)
            {
                var msg = new WinAPI.Windows.MSG();
                msg.hwnd = ClientWindowHandle;
                msg.lParam = lParam;
                msg.message = wm;
                msg.pt = new WinAPI.Windows.POINT();
                msg.time = WinAPI.SendInputApi.GetTickCount();
                msg.wParam = (int)vk;
                WinAPI.Windows.TranslateMessage(ref msg);
                //WinAPI.Windows.GetMessage(out msg, ClientWindowHandle, Mubox.WinAPI.WM.CHAR, WinAPI.WM.UNICHAR);
                //WinAPI.Windows.SendMessage(ClientWindowHandle, wm, new UIntPtr(wParam), new UIntPtr(lParam));
            }

            // TODO: this expression should probably be checking for == UP, but the individual key states need to be refactored to check current state first)
            // NOTE: if subsequent keys still rely on this state, it will be re-set as expected because of the sister CASE code above
            if ((flags & WinAPI.WindowHook.LLKHF.UP) != WinAPI.WindowHook.LLKHF.UP)
            {
                if ((cas & WinAPI.CAS.CONTROL) != 0)
                {
                    Process(new KeyboardInput
                    {
                        VK = WinAPI.VK.Control,
                        Flags = WinAPI.WindowHook.LLKHF.UP,
                        Scan = (uint)WinAPI.SendInputApi.MapVirtualKey(WinAPI.VK.Control, WinAPI.SendInputApi.MAPVK.MAPVK_VK_TO_VSC),
                        Time = time,
                        CAS = (WinAPI.CAS)0,
                    });
                }
                if ((cas & WinAPI.CAS.ALT) != 0)
                {
                    Process(new KeyboardInput
                    {
                        VK = WinAPI.VK.Menu,
                        Flags = WinAPI.WindowHook.LLKHF.UP,
                        Scan = (uint)WinAPI.SendInputApi.MapVirtualKey(WinAPI.VK.Menu, WinAPI.SendInputApi.MAPVK.MAPVK_VK_TO_VSC),
                        Time = time,
                        CAS = (WinAPI.CAS)0,
                    });
                }
                if ((cas & WinAPI.CAS.SHIFT) != 0)
                {
                    Process(new KeyboardInput
                    {
                        VK = WinAPI.VK.Shift,
                        Flags = WinAPI.WindowHook.LLKHF.UP,
                        Scan = (uint)WinAPI.SendInputApi.MapVirtualKey(WinAPI.VK.Shift, WinAPI.SendInputApi.MAPVK.MAPVK_VK_TO_VSC),
                        Time = time,
                        CAS = (WinAPI.CAS)0,
                    });
                }
            }
        }
Esempio n. 6
0
        private void KeyboardInputHook_KeyboardInputReceived(object sender, KeyboardInput e)
        {
            if (this.Keyboard_DefaultAction != null)
            {
                if (this.Keyboard_DefaultAction(e) || e.Handled)
                {
                    return;
                }
            }

            Func<KeyboardInput, bool> action = null;
            var keyAction = Keyboard_ActionMap[(WinAPI.VK)e.VK];
            if (keyAction != null)
            {
                if (keyAction.TryGetValue(e.WM, out action))
                {
                    if (action(e) || e.Handled)
                    {
                        return;
                    }
                }
                //else
                //{
                //    Console.WriteLine("???? MISSING WM ACTION IN MESSAGE MAP - vk=" + (WinAPI.VK)e.VK + " wm=" + e.WM);
                //}
            }
            else
            {
                Console.WriteLine("???? MISSING KEY ACTION IN KEY MAP - vk=" + (WinAPI.VK)e.VK + " wm=" + e.WM);
            }

            if (!Mubox.Configuration.MuboxConfigSection.Default.IsCaptureEnabled)
            {
                return;
            }

            Mubox.Extensions.ExtensionManager.Instance.OnKeyboardInputReceived(sender, e);

            ClientBase activeClient = this.ActiveClient;

            if (Mubox.Configuration.MuboxConfigSection.Default.Profiles.ActiveProfile.EnableMulticast && !ActiveClientOnly(e))
            {
                e.Handled = true;

                ClientBase[] clients = GetCachedClients();

                KeySetting globalKeySetting;
                if (MuboxConfigSection.Default.Profiles.ActiveProfile.Keys.TryGetKeySetting((WinAPI.VK)e.VK, out globalKeySetting))
                {
                    if (globalKeySetting.RoundRobinKey)
                    {
                        if (clients.Length > 0)
                        {
                            int clientIndex = roundRobinTable[(int)e.VK];
                            if (e.Flags.HasFlag(WinAPI.WindowHook.LLKHF.UP))
                            {
                                // we only update round-robin target on key-up, otherwise two different clients receive keydown vs. keyup events
                                roundRobinTable[(int)e.VK] = (byte)clientIndex + 1;
                            }
                            ClientBase client = clients[clientIndex % clients.Length];
                            InputToClient(e, client);
                            return;
                        }
                    }
                }

                foreach (ClientBase client in clients)
                {
                    InputToClient(e, client);
                }
            }
            else if (activeClient != null)
            {
                e.Handled = true;
                ForwardEventToClient(e, activeClient);
            }
        }
Esempio n. 7
0
 private static void InputToClient(KeyboardInput e, ClientBase client)
 {
     // this method basically applies CAS settings and calls ForwardEventToClient
     byte cas = 0;
     var clientSettings = Mubox.Configuration.MuboxConfigSection.Default.Profiles.ActiveProfile.ActiveClient;
     if (clientSettings != null)
     {
         if (clientSettings.Name.Equals(client.DisplayName, StringComparison.InvariantCultureIgnoreCase))
         {
             Mubox.Configuration.KeySetting keySetting;
             if (clientSettings.Keys.TryGetKeySetting((WinAPI.VK)e.VK, out keySetting) && keySetting.EnableNoModActiveClient)
             {
                 cas = (byte)e.CAS;
                 e.CAS = (WinAPI.CAS)0;
             }
         }
     }
     ForwardEventToClient(e, client);
     if (cas != 0)
     {
         e.CAS = (WinAPI.CAS)cas;
     }
 }
Esempio n. 8
0
 private static void ForwardEventToClient(KeyboardInput e, ClientBase clientBase)
 {
     try
     {
         e.WindowStationHandle = clientBase.WindowStationHandle;
         e.WindowDesktopHandle = clientBase.WindowDesktopHandle;
         e.WindowHandle = clientBase.WindowHandle;
         clientBase.Dispatch(e);
     }
     catch (Exception ex)
     {
         Mubox.Control.Network.Server.RemoveClient(clientBase);
         ex.Log();
     }
 }
Esempio n. 9
0
 private static bool ActiveClientOnly(KeyboardInput e)
 {
     // TODO optimize !!! iterating 'all keys' looking for a match is a waste of CPU, perhaps a bitmap of Win32.VK makes sense, but it needs to be synchronized against the config (perhaps on Save)
     bool activeClientOnly = false;
     foreach (var item in Mubox.Configuration.MuboxConfigSection.Default.Profiles.ActiveProfile.Keys.Cast<Mubox.Configuration.KeySetting>())
     {
         if (item.ActiveClientOnly && (WinAPI.VK)e.VK == item.InputKey)
         {
             activeClientOnly = true;
             break;
         }
     }
     return activeClientOnly;
 }
Esempio n. 10
0
 public override void Dispatch(KeyboardInput e)
 {
     #if DEBUG
     ("Dispatch(" + _displayName + ") " + Convert.ToString(e)).Log();
     #endif
     ServerTxPerformanceIncrement("KB");
     try
     {
         Send(e);
         base.Dispatch(e);
     }
     catch
     {
         Control.Network.Server.RemoveClient(this);
     }
 }