Question

Basically, for the start, I want to reproduce the functionality of WizMouse or KatMouse. A related Superuser question is here.

What Windows APIs would I need for that?

Also, as a second step, I thought of implementing something as the MacOSX scroll acceleration and pixel-exact scrolling. (Basically, you scroll always pixel-by-pixel, but when you move the scroll wheel fast, it accelerates more than linearly, e.g. quadratic, to the scroll wheel speed. That way, you can scroll way more and faster to the end of a long page, and at the same time, you can scroll way less and more exact.)

Is there a way to scroll some element only by a single pixel? (I can implement all the remaining logic by myself.)

This question is tagged with C++ and Winapi, but if it is easier with some other Windows-API and some other language, I'm also open for that.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top