예제 #1
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,
                    });
                }
            }
        }
예제 #2
0
        private void Process(MouseInput mouseInput)
        {
            // denormalize coordinates into client coordinates (we should always expect normalized coordinates, whether coordinates are absolute or relative)
            ushort x = (ushort)Math.Ceiling((double)(mouseInput.Point.X) * ((double)ClientWindowRect.Width / 65536.0));
            ushort y = (ushort)Math.Ceiling((double)(mouseInput.Point.Y) * ((double)ClientWindowRect.Height / 65536.0));

            var clientRelativeCoordinates = WinAPI.MACROS.MAKELPARAM(x, y);

            var wm = WinAPI.WM.USER;

            switch ((mouseInput.Flags | WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_ABSOLUTE) ^ WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_ABSOLUTE)
            {
                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_MOVE:
                    wm = WinAPI.WM.MOUSEMOVE;
                    break;

                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_LEFTDOWN:
                    //WinAPI.Cursor.SetCapture(ClientWindowHandle);
                    wm = WinAPI.WM.LBUTTONDOWN;
                    CurrentMK |= WinAPI.Windows.MK.MK_LBUTTON;
                    break;

                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_LEFTUP:
                    //var priorCapture = WinAPI.Cursor.GetCapture();
                    //if (priorCapture == IntPtr.Zero)
                    //{
                    //    ("GetCapture Fail").LogWarn();
                    //}
                    //else
                    //{
                    //    WinAPI.Cursor.ReleaseCapture();
                    //}
                    wm = WinAPI.WM.LBUTTONUP;
                    CurrentMK = (CurrentMK | WinAPI.Windows.MK.MK_LBUTTON) ^ WinAPI.Windows.MK.MK_LBUTTON;
                    break;

                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_RIGHTDOWN:
                    //WinAPI.Cursor.SetCapture(ClientWindowHandle);
                    wm = WinAPI.WM.RBUTTONDOWN;
                    CurrentMK |= WinAPI.Windows.MK.MK_RBUTTON;
                    break;

                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_RIGHTUP:
                    //var priorCapture = WinAPI.Cursor.GetCapture();
                    //if (priorCapture == IntPtr.Zero)
                    //{
                    //    ("GetCapture Fail").LogWarn();
                    //}
                    //else
                    //{
                    //    WinAPI.Cursor.ReleaseCapture();
                    //}
                    wm = WinAPI.WM.RBUTTONUP;
                    CurrentMK = (CurrentMK | WinAPI.Windows.MK.MK_RBUTTON) ^ WinAPI.Windows.MK.MK_RBUTTON;
                    break;

                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_MIDDLEDOWN:
                    wm = WinAPI.WM.MBUTTONDOWN;
                    CurrentMK |= WinAPI.Windows.MK.MK_MBUTTON;
                    break;

                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_MIDDLEUP:
                    wm = WinAPI.WM.MBUTTONUP;
                    CurrentMK = (CurrentMK | WinAPI.Windows.MK.MK_MBUTTON) ^ WinAPI.Windows.MK.MK_MBUTTON;
                    break;

                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_XDOWN:
                    wm = WinAPI.WM.XBUTTONDOWN;
                    switch (WinAPI.MACROS.GET_XBUTTON_WPARAM(mouseInput.MouseData))
                    {
                        case WinAPI.MACROS.XBUTTONS.XBUTTON1:
                            CurrentMK |= WinAPI.Windows.MK.MK_XBUTTON1;
                            break;

                        case WinAPI.MACROS.XBUTTONS.XBUTTON2:
                            CurrentMK |= WinAPI.Windows.MK.MK_XBUTTON2;
                            break;
                    }
                    break;

                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_XUP:
                    wm = WinAPI.WM.XBUTTONUP;
                    switch (WinAPI.MACROS.GET_XBUTTON_WPARAM(mouseInput.MouseData))
                    {
                        case WinAPI.MACROS.XBUTTONS.XBUTTON1:
                            CurrentMK = (CurrentMK | WinAPI.Windows.MK.MK_XBUTTON1) ^ WinAPI.Windows.MK.MK_XBUTTON1;
                            break;

                        case WinAPI.MACROS.XBUTTONS.XBUTTON2:
                            CurrentMK = (CurrentMK | WinAPI.Windows.MK.MK_XBUTTON2) ^ WinAPI.Windows.MK.MK_XBUTTON2;
                            break;
                    }
                    break;

                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_WHEEL:
                case WinAPI.SendInputApi.MouseEventFlags.MOUSEEVENTF_HWHEEL:
                    wm = WinAPI.WM.MOUSEWHEEL;
                    break;

                default:
                    wm = mouseInput.WM;
                    break;
            }

            WinAPI.Windows.PostMessage(ClientWindowHandle, wm, new UIntPtr(mouseInput.MouseData), new UIntPtr(clientRelativeCoordinates));
        }