GetCursorPos
will let you get the coordinates of the mouse pointer. After that, WindowFromPoint
will let you figure out which window is at that point. Apparently figuring out which window is at a given point is complicated, though, so you'll want to do some experimenting with the different ...FromPoint...
APIs (from a look at that Old New Thing blogpost, WindowFromPoint
should work just fine for your purposes).
To trap the mouse scroll messages, you'll want to use SetWindowsHookEx
with WH_MOUSE_LL
. This will send you any and all mouse messages. Be sure you call CallNextHookEx
for any messages other than WM_MOUSEWHEEL
or WM_HMOUSEWHEEL
; you don't want to eat all the messages! You do want to eat WM_MOUSEWHEEL
and WM_HMOUSEWHEEL
events, though, since you're manually sending them to an alternate window.
I'm a little less certain about the next part. I think you'll want to pass WM_MOUSEWHEEL
directly to the window under the cursor, but you'll need to make sure your hook doesn't eat it. (The best way to accomplish this might be to have the hook procedure determine whether the WM_MOUSEWHEEL
message is already being passed to the window under the cursor, and only process/eat it if it's not.) You can also take advantage of the message's wParam
to set how quickly you're scrolling. I don't believe you'll be able to scroll pixel-by-pixel, but you can use the minimum scrolling distance (WHEEL_DELTA * 1
) initially, and scale that multiplier up as you scroll faster and faster. Rinse and repeat for WM_HMOUSEWHEEL
.
The one thing you'll need to be very careful about is timeouts. From the documentation on WH_MOUSE_LL
hooks:
The hook procedure should process a message in less time than the data entry specified in the LowLevelHooksTimeout value in the following registry key: HKEY_CURRENT_USER\Control Panel\Desktop
The value is in milliseconds. If the hook procedure times out, the system passes the message to the next hook. However, on Windows 7 and later, the hook is silently removed without being called. There is no way for the application to know whether the hook is removed.
The FAQ for X-Button Mouse Control, an app that does something similar to what you're looking for, says (emphasis mine):
When using on Windows 7, XMBC can stop responding to mouse click seemingly randomly. This is not strictly a bug in XMBC but a change in the behaviour of Windows. Windows 7 introduced the concept of a timeout for system hooks (the method XMBC uses to monitor the mouse). If the CPU is busy (eg. playing HD movies) XMBC may not be scheduled (by windows) in time to respond to the hook before this timeout occurs. When this happens, the hook is removed without notification (thanks Microsoft!) and XMBC appears to have stopped working. Restarting it or pressing Apply in the settings screen fixes the problem until it happens again.
The only solution to this is to increase the LowLevelHookTimeout value (in the registry for now).
It's highly likely your software will face the same problem. You'll want to be sure you document it and/or adjust that Registry key yourself to provide a higher timeout value.