I'm trying to make my own toolbar. The idea is that it sits in the non-client area so it's not requiring a child window. However, I've been stumped by the mouse handling. The idea is that each "button" should display an alternate image when the mouse is over it (sort of highlighted). At first, i was just processing WM_NCMOUSEMOVE but quickly found that if the mouse wanders out of the window, the last button highlighted would stay highlighted.
My next approach was to capture the mouse when it came into the toolbar rectangle and release it when the mouse drifts out. This works good except for the fact that when the mouse is captured, key combos like Alt+F4 etc don't work!
Does anyone know of an alternate solution for tracking the mouse position?? Even in the client area?? I think WinNT has TrackMouseEvent, but this isn't quite right and furthermore it is on the wrong platform.

Thanks all,

Posted on 2002-06-08 18:13:40 by chorus
TrackMouseEvent is available on win98 as well and I believe all machines that have IE 5 installed. It really is the best solution, but if you need compatibility with other platforms, you can also use a timer. Start the timer when the mouse is over your window, in the timer callback check if the mouse is still over the window, if not, kill the timer. Mouse capturing isn't a good idea because of the side effects.

More info: http://www.microsoft.com/msj/defaultframe.asp?page=/msj/1098/c++/c++1098.htm

Posted on 2002-06-09 03:15:09 by Thomas
Wow what a great idea Thomas, i have also struggled with this and never thought of using a timer

<heads off on a new coding spreee :-)
Posted on 2002-06-09 03:21:04 by Terab
Thomas, thanks for the link! It was excellent!

I'm going to try the timer approach, but another idea has also come to mind. I've seen an application that changes the message loop slightly. Instead of GetMessage it uses PeekMessage, and if no message is waiting it does some default action (I think it was a little game and it was bitblt frames when not busy). Perhaps I could use this approach to get good results. Dunno if this will be better or worse than the timer...

Thanks again,

Posted on 2002-06-09 13:15:15 by chorus
If you replace GetMessage by PeekMessage, the message loop would run many times a second. GetMessage actually waits in an idle state until a message arrives, while PeekMessage just looks for a message and returns.
So any checking code in the message loop would execute very often, probably more than necessary. Windows will also show a 100% CPU usage if you use PeekMessage.

Posted on 2002-06-09 13:54:49 by Thomas
Thomas, you're right. Didn't think PeekMessage consumed that much CPU time... I thought it would only use the amount of timeslice that windows gives to an application.

Anyways, the timer method works really well! 50 ms seems good, maybe even a longer timeslice would work just as well. BTW, instead of implementing the timer everytime the mouse enters the toolbar I just set it with the creation of the window and kill it on WM_DESTROY. This doesn't seem to affect CPU time at all and means I only have to process the WM_TIMER instead of watching WM_MOUSEMOVE to set it and kill it all the time.

Thanks again

Posted on 2002-06-09 14:25:22 by chorus
I'm not sure if peekmessage takes that much CPU time, I believe windows bases the CPU time on the frequency of GetMessage/PeekMessage calls. But 100% usage isn't very good and it's overkill anyway.

Posted on 2002-06-09 14:28:28 by Thomas
You know, I have to wonder how menus, etc pull this off. As I said before, the timer works very good. But it still doesn't have the *exact* responsiveness that menus, etc have. Not that I'm complaining, you have to move the mouse back and forth really quickly to trip up the toolbar. But it can be done. Whereas if you sit on any menu, you can move the mouse back and forth as fast as you want and it'll track it exactly... I wonder what kind of trick they're using?

Anyways, thanks again for all the advice!
Posted on 2002-06-09 15:00:20 by chorus
WM_MOUSEMOVE would give a better response, as it will trigger as soon as the mouse enters the window instead of when the timer interval elapses (worst case 50ms delay in your case).
The combination of WM_MOUSEMOVE and TrackMouseEvent is the best one. You could use GetProcAddress to see whether it's available and only use the timer method when it's not.

Posted on 2002-06-09 16:18:36 by Thomas