views:

479

answers:

1

My goal is to make a floating toolbar (as its own C# application), and when the user uses the scrollwheel over me I want to change the buttons that are visible. Sounds easy enough, should just be a matter of this one-liner:

MouseWheel += new MouseEventHandler(Form1_MouseWheel);

The problem I am having is that the mouse wheel handler is only invoked when my application has focus. That means the user has to first click, and then mousewheel. That won't do for what I'm trying to do.

I can hook the MouseHover event handler and call form.Activate() then, to get focus. That's suboptimal because if the user uses the scrollwheel immediately after mousing over my application (instead of waiting a little), the focus will still be on the previous app and it'll get the mousewheel event.

A natural thing to do would be to hook the MouseEnter event and call Activate() there, but then instead of my application coming to the front, its icon starts to blink on the task bar. I'm using Win7, but this problem is probably older than this.

Ideally, what I'd like to do would be to detect the mousewheel events without having to worry about whether my application has focus. It would really be better for the previous application to keep input focus, so for example if the user's in Notepad they can type, mouse over to my app, use the scroll wheel, look at what they see and decide to just resume typing in Notepad. Ideally I don't want them to have to click even once in this scenario.

I'll settle for a solution that switches focus to my application, though, if there's no other way.

What I have so far uses C# and Windows Forms, but I'd be open to using something different if that can solve my problems.

So: how can I see those mousewheel events without the user having to click to focus my application first?

+2  A: 

If you need to catch mouse events outside your application, you can use a global system hook. There's a good .NET implementation here

Thomas Levesque
Thomas, thanks - this is very close but not all the way there. The code you link can detect a mousewheel movement, but it doesn't tell me *which way* the wheel went. I see that it puts in its own MouseFunc handler, and looking up the WM_MOUSEWHEEL message indicates that wparam should contain the delta and modifier keys. However it seems to always be 522 for me - so 0 in the high word instead of the delta I'm expecting. It seems I need a little bit more help to get to the solution! Assistance would be appreciated :)
redtuna
522 is the value of the WM_MOUSEWHEEL constant... there must be something wrong in this implementation, it seems that the message id is passed to the HookCallback as the wparam argument, instead of the code parameter :S
Thomas Levesque
My bad; the documentation for WM_MOUSEWHEEL does not actually describe what one gets in MouseProc. lParam is 522, and wParam is a pointer to MOUSEHOOKSTRUCT. That structure does not seem to have anything about the mouse wheel, though: the documentation ( http://msdn.microsoft.com/en-us/library/ms644968%28VS.85%29.aspx ) only lists a point, window handle, hit test and undocumented data.So the question remains unanswered: how can I tell which way the mousewheel was moved?
redtuna
OK, I finally got it. The trick is to either hook WH_MOUSE_LL and cast lparam to a MSLLHOOKSTRUCT, or hook WH_MOUSE and cast lparam to a MOUSEHOOKSTRUCTEX.
redtuna