| 226 | |
| 227 | |
| 228 | LRESULT CALLBACK LowLevelMouseProc(int aCode, WPARAM wParam, LPARAM lParam) |
| 229 | { |
| 230 | // code != HC_ACTION should be evaluated PRIOR to considering the values |
| 231 | // of wParam and lParam, because those values may be invalid or untrustworthy |
| 232 | // whenever code < 0. |
| 233 | if (aCode != HC_ACTION) |
| 234 | return CallNextHookEx(g_MouseHook, aCode, wParam, lParam); |
| 235 | |
| 236 | MSLLHOOKSTRUCT &event = *(PMSLLHOOKSTRUCT)lParam; // For convenience, maintainability, and possibly performance. |
| 237 | |
| 238 | // Make all mouse events physical to try to simulate mouse clicks in games that normally ignore |
| 239 | // artificial input. |
| 240 | //event.flags &= ~LLMHF_INJECTED; |
| 241 | |
| 242 | if (!(event.flags & LLMHF_INJECTED)) // Physical mouse movement or button action (uses LLMHF vs. LLKHF). |
| 243 | g_TimeLastInputPhysical = g_TimeLastInputMouse = GetTickCount(); |
| 244 | // Above: Don't use event.time, mostly because SendInput can produce invalid timestamps on such events |
| 245 | // (though in truth, that concern isn't valid because SendInput's input isn't marked as physical). |
| 246 | // Another concern is the comments at the other update of "g_TimeLastInputPhysical" elsewhere in this file. |
| 247 | // A final concern is that some drivers might be faulty and might not generate an accurate timestamp. |
| 248 | |
| 249 | if (wParam == WM_MOUSEMOVE) // Only after updating for physical input, above, is this checked. |
| 250 | return (g_BlockMouseMove && !(event.flags & LLMHF_INJECTED)) ? 1 : CallNextHookEx(g_MouseHook, aCode, wParam, lParam); |
| 251 | // Above: In v1.0.43.11, a new mode was added to block mouse movement only since it's more flexible than |
| 252 | // BlockInput (which keybd too, and blocks all mouse buttons too). However, this mode blocks only |
| 253 | // physical mouse movement because it seems most flexible (and simplest) to allow all artificial |
| 254 | // movement, even if that movement came from a source other than an AHK script (such as some other |
| 255 | // macro program). |
| 256 | |
| 257 | // MSDN: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MOUSEMOVE, WM_MOUSEWHEEL [, WM_MOUSEHWHEEL], WM_RBUTTONDOWN, or WM_RBUTTONUP. |
| 258 | // But what about the middle button? It's undocumented, but it is received. |
| 259 | // What about doubleclicks (e.g. WM_LBUTTONDBLCLK): I checked: They are NOT received. |
| 260 | // This is expected because each click in a doubleclick could be separately suppressed by |
| 261 | // the hook, which would make it become a non-doubleclick. |
| 262 | vk_type vk = 0; |
| 263 | sc_type sc = 0; // To be overridden if this even is a wheel turn. |
| 264 | short wheel_delta; |
| 265 | bool key_up = true; // Set default to safest value. |
| 266 | |
| 267 | switch (wParam) |
| 268 | { |
| 269 | case WM_MOUSEWHEEL: |
| 270 | case WM_MOUSEHWHEEL: // v1.0.48: Lexikos: Support horizontal scrolling in Windows Vista and later. |
| 271 | // MSDN: "A positive value indicates that the wheel was rotated forward, away from the user; |
| 272 | // a negative value indicates that the wheel was rotated backward, toward the user. One wheel |
| 273 | // click is defined as WHEEL_DELTA, which is 120." Testing shows that on XP at least, the |
| 274 | // abs(delta) is greater than 120 when the user turns the wheel quickly (also depends on |
| 275 | // granularity of wheel hardware); i.e. the system combines multiple turns into a single event. |
| 276 | wheel_delta = GET_WHEEL_DELTA_WPARAM(event.mouseData); // Must typecast to short (not int) via macro, otherwise the conversion to negative/positive number won't be correct. |
| 277 | if (wParam == WM_MOUSEWHEEL) |
| 278 | vk = wheel_delta < 0 ? VK_WHEEL_DOWN : VK_WHEEL_UP; |
| 279 | else |
| 280 | vk = wheel_delta < 0 ? VK_WHEEL_LEFT : VK_WHEEL_RIGHT; |
| 281 | sc = (wheel_delta > 0 ? wheel_delta : -wheel_delta); // Note that sc is unsigned. |
| 282 | key_up = false; // Always consider wheel movements to be "key down" events. |
| 283 | break; |
| 284 | case WM_LBUTTONUP: vk = VK_LBUTTON; break; |
| 285 | case WM_RBUTTONUP: vk = VK_RBUTTON; break; |
nothing calls this directly
no test coverage detected