diff --git a/KeyboardChatterBlocker/KeyBlocker.cs b/KeyboardChatterBlocker/KeyBlocker.cs index 3cb17d2..f439b1b 100644 --- a/KeyboardChatterBlocker/KeyBlocker.cs +++ b/KeyboardChatterBlocker/KeyBlocker.cs @@ -62,7 +62,8 @@ public void AutoEnableMouse() { if (KeysToChatterTime[KeysHelper.KEY_MOUSE_LEFT].HasValue || KeysToChatterTime[KeysHelper.KEY_MOUSE_RIGHT].HasValue || KeysToChatterTime[KeysHelper.KEY_MOUSE_MIDDLE].HasValue - || KeysToChatterTime[KeysHelper.KEY_MOUSE_FORWARD].HasValue || KeysToChatterTime[KeysHelper.KEY_MOUSE_BACKWARD].HasValue) + || KeysToChatterTime[KeysHelper.KEY_MOUSE_FORWARD].HasValue || KeysToChatterTime[KeysHelper.KEY_MOUSE_BACKWARD].HasValue + || KeysToChatterTime[KeysHelper.KEY_WHEEL_CHANGE].HasValue) { Interceptor.EnableMouseHook(); } @@ -277,7 +278,7 @@ public bool AllowKeyUp(Keys key) return true; } KeyIsDown[key] = false; - if (!KeysWereDownBlocked[key]) // Down wan't blocked = allow it. + if (!KeysWereDownBlocked[key]) // Down wasn't blocked = allow it. { return true; } diff --git a/KeyboardChatterBlocker/KeyboardInterceptor.cs b/KeyboardChatterBlocker/KeyboardInterceptor.cs index c62adc1..80f6fe8 100644 --- a/KeyboardChatterBlocker/KeyboardInterceptor.cs +++ b/KeyboardChatterBlocker/KeyboardInterceptor.cs @@ -36,7 +36,8 @@ public class KeyboardInterceptor : IDisposable public const int WM_LBUTTONDOWN = 0x0201, WM_LBUTTONUP = 0x0202, WM_RBUTTONDOWN = 0x0204, WM_RBUTTONUP = 0x0205, WM_MBUTTONDOWN = 0x0207, WM_MBUTTONUP = 0x0208, - WM_XBUTTONDOWN = 0x020B, WM_XBUTTONUP = 0x020C; + WM_XBUTTONDOWN = 0x020B, WM_XBUTTONUP = 0x020C, + WM_MOUSEWHEEL = 0x020A; /// /// An array of falses, except for the WParam values that are handled by this program. @@ -166,6 +167,12 @@ public IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam) return CallNextHookEx(KeyboardHookID, nCode, wParam, lParam); } + /// + /// The direction of last mouse wheel delta (positive or negative, as 1 or -1), + /// used to trigger "wheel_change" detection. + /// + public int LastWheelDirection = 0; + /// /// The primary mouse hook callback. /// @@ -176,10 +183,26 @@ public IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam) public IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam) { int wParamInt = (int)wParam; - if (nCode >= 0 && wParamInt < 1024 && HANDLED_WPARAMS[wParamInt]) + if (wParamInt == WM_MOUSEWHEEL) + { + MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); + short wheelDelta = (short)((hookStruct.mouseData) >> 16); + int wheelDirection = Math.Sign(wheelDelta); + if (LastWheelDirection != wheelDirection) + { + bool allow = KeyBlockHandler.AllowKeyDown(KeysHelper.KEY_WHEEL_CHANGE, true); + KeyBlockHandler.AllowKeyUp(KeysHelper.KEY_WHEEL_CHANGE); + if (!allow) + { + return (IntPtr)1; + } + LastWheelDirection = wheelDirection; + } + } + else if (nCode >= 0 && wParamInt < 1024 && HANDLED_WPARAMS[wParamInt]) { bool isDown = wParamInt == WM_LBUTTONDOWN || wParamInt == WM_RBUTTONDOWN || wParamInt == WM_MBUTTONDOWN || wParamInt == WM_XBUTTONDOWN; - if (isDown || wParamInt == WM_LBUTTONUP || wParamInt == WM_RBUTTONUP || wParamInt == WM_MBUTTONUP || wParamInt == WM_XBUTTONUP) + if (isDown || wParamInt == WM_LBUTTONUP || wParamInt == WM_RBUTTONUP || wParamInt == WM_MBUTTONUP || wParamInt == WM_XBUTTONUP || wParamInt == WM_MOUSEWHEEL) { Keys key; if (wParamInt == WM_LBUTTONDOWN || wParamInt == WM_LBUTTONUP) diff --git a/KeyboardChatterBlocker/KeysHelper.cs b/KeyboardChatterBlocker/KeysHelper.cs index a20dcbc..735de5a 100644 --- a/KeyboardChatterBlocker/KeysHelper.cs +++ b/KeyboardChatterBlocker/KeysHelper.cs @@ -16,7 +16,8 @@ public static class KeysHelper /// 'Keys' enum values offset from the main enum option, as stand-ins for mouse keys. /// public static Keys KEY_MOUSE_LEFT = (Keys)513, KEY_MOUSE_RIGHT = (Keys)514, KEY_MOUSE_MIDDLE = (Keys)515, - KEY_MOUSE_FORWARD = (Keys)516, KEY_MOUSE_BACKWARD = (Keys)517; + KEY_MOUSE_FORWARD = (Keys)516, KEY_MOUSE_BACKWARD = (Keys)517, + KEY_WHEEL_CHANGE = (Keys)518; /// /// Tries to get the key for the given name. @@ -56,6 +57,11 @@ public static bool TryGetKey(string name, out Keys key) key = KEY_MOUSE_BACKWARD; return true; } + else if (lowered == "wheel_change") + { + key = KEY_WHEEL_CHANGE; + return true; + } key = default; return false; } @@ -66,7 +72,7 @@ public static bool TryGetKey(string name, out Keys key) /// The key to stringify. public static string Stringify(this Keys key) { - if ((int)key >= 513 && (int)key <= 517) + if ((int)key >= 513 && (int)key <= 518) { switch ((int)key) { @@ -75,6 +81,7 @@ public static string Stringify(this Keys key) case 515: return "mouse_middle"; case 516: return "mouse_forward"; case 517: return "mouse_backward"; + case 518: return "wheel_change"; } } return key.ToString(); diff --git a/README.md b/README.md index 7eba18c..7e0c43e 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ I've taken a similar approach to the software solutions mentioned above, but wit - You can theoretically block any key on a keyboard that registers as a standard keypress. This includes weird special keys like a volume wheel. You might want to set volume wheels to threshold of zero if you have one. Extremely specialized keys (such as G Keys) might not be standard keypresses and thus not be blockable. If in doubt: try it and see! - You can block mouse buttons if you want (Left/Right/Middle/Forward/Backward). Be careful if you block left mouse button chatter: if you set the limit too high, you might become unable to double-click. If you get stuck, you can either uncheck the `Enabled` box to regain control and fix that, or, if needed, use Task Manager to kill the blocker program, and then edit the config file (see config notes below). +- You can manually edit your config to add `wheel_change` key detector, if you have a counter-scroll/wheel bounce issue similar to what's described in [issue #17](https://github.com/mcmonkeyprojects/KeyboardChatterBlocker/issues/17). - This only works in user-space. That is, the Windows login screen and other sensitive Windows protected input areas will not have chatter blocked. You might want to use a PIN or other login method to avoid chatter problems that affect a password login (see also [issue #7](https://github.com/mcmonkeyprojects/KeyboardChatterBlocker/issues/7)). - You can add a list of programs that will cause the blocker to automatically disable when those programs are open. This is useful for example with games, as you often don't want rapid keystrokes blocked while gaming. This will be matched by executable name. - If you play online games, be careful that some anticheat software may block you for running this software, as it does control and alter keyboard input from software, which likely appears similar to cheat programs. See also [issue #15 which reports a VAC ban in CSGO from running KeyboardChatterBlocker](https://github.com/mcmonkeyprojects/KeyboardChatterBlocker/issues/15).