I am trying to implement a popup menu that opens on a mousemove message rather than a right mouse click. When the cursor is in a particular region of the client window, the popup menu should be displayed. If the mouse moves to a different region, the original popup menu should 'disappear' and a modified menu should appear that is specific to that region.
I am finding this quite difficult to get working - does anyone have any ideas for me? This has been my approach so far:
In the OnMouseMove handler - I check the cursor coordinates and create/load the popup menu specific to the region. Because I am using TrackPopupMenu to display the popup menu, no other mouse move messages were getting through until I closed that menu or select an item from it.
My attempt at a solution (after searching on CodeGuru) was to use a thread specific hook to catch the mousemove message - to do this I used:
In this function I check if it is a mousemove message and then call the same code to check the region and create a new popup menu.
My problem is that the popup menu will display the first time and then will remain on the screen until I close it or select an item from it .... if I step into the code, the MouseHook function is being called and sometimes fires the code to create a new menu, but it doesn't seem to work. I am not sure if my problem lies in how I am implementing the creation of the menu or how I am trying to create and use the windows hook.
Sorry for the lengthy explanation, but can anyone shed some light on this problem? Or perhaps suggest a better way to achieve the same result??
thanks,
Em
Last edited by Emster; April 14th, 2004 at 05:46 PM.
At a guess, the problem is probably due to the open menu. You need to dismiss the one that is open before trying to pop up the next one. My only suggestion on doing this, is to use SetFocus() onto a different control so that the menu gets killed. Then create the new one.
Please use meaningful question titles - "Help me" does not let me know whether I can help with your question, and I am unlikely to bother reading it. Please remember to rate useful answers. It lets us know when a question has been answered.
Originally posted by Emster
Because I am using TrackPopupMenu to display the popup menu, no other mouse move events were getting through until I close that menu or select an item from it.
To clarify you should refer to handling mouse messages not events. Events are handled in VB.
Anytime menu pops up menu enters its modal loop and captures mouse. Roger’s guess is correct. You have to dismiss menu somehow before you invoke another one.
GetLastError returns 0x000005A6 - Popup menu already active.
Originally posted by Emster
My attempt at a solution (after searching on CodeGuru) was to use a thread specific hook to catch the mousemove event - to do this I used:
.
.
. In this function I check if it is a mousemove event and then fire the same code to check the region and create a new popup menu.
this approach is correct. It allows you to catch WM_MOUSEMOVE message and act on it. Again nothing is fired here this is C++ MFC programming - mouse message is being sent to a window and you catch it inside of the hook.
Originally posted by Emster
My problem is that the popup menu will display the first time and then will remain on the screen until I close it or select an item from it
You can use several approaches to dismiss menu.
Some coding: call SendInput. You with INPUT dwFlags set to MOUSEEVENTF_LEFTDOWN. You would have to make sure that cursor is not in menu area.
The simplest. Use PostMessage(WM_LBUTTONDOWN, 0, 0); it always works.
You can also use FindWindow to find menu and DestroyWindow to dismiss menu.
There are only 10 types of people in the world: Those who understand binary and those who do not.
Thankyou Roger Allen and Kirants for your suggestions on closing the menu and a special thanks to JohnCz for your detailed help and explanation of my problem (+ corrections of my programming terminology ).
I have now solved my problem by closing the first popup menu, then creating and displaying the new one. I had previously tried to send an LBUTTONDOWN message to close it, but was doing it incorrectly - so now I have corrected my code it works! I am now going to try the other alternatives suggested to see if they work equally as well.
After solving my initial problem with this popup menu, I have run into another one. I thought I would continue in this thread as all my background info is here.
Anyway - the problem is that the FIRST time my popup menu is displayed, moving the mouse into another region will not dismiss the menu. After some debugging it seems that although I have set the windows hook to capture the mouse move message, NO mouse move messages are actually getting through (ie: the hook is not catching them, so my code to close the menu and reopen is not being reached).
If I close that initial menu and move the mouse into a new region, it works fine from then on. It is only failing on the first time.
Does anyone have any ideas about this? Could something else be stopping the mouse messages from getting through?
WH_MOUSE
Windows calls this hook when a GetMessage or a PeekMessage function is called and Windows has a mouse message to process. Like the WH_KEYBOARD hook, this filter function receives a hook code, which indicates whether the message is being removed (HC_NOREMOVE), an identifier specifying the mouse message, and the x and y coordinates of the mouse. Filters can tell Windows to discard the message. Filters for this hook must reside in a DLL.
I have not used a DLL for my WH_MOUSE filter function - perhaps this is my problem. I was under the impression that I only had to use a DLL for implementing system-wide hooks.... but perhaps the WH_MOUSE hook is the exception.
Has anyone else come across this? I would appreciate your feedback if you have...
Originally posted by Emster
I was under the impression that I only had to use a DLL for implementing system-wide hooks.... but perhaps the WH_MOUSE hook is the exception.
I am not sure what do you mean by another region in your previous post.
You are correct. System wide hooks would have to be in a dll since that dll is loaded into a address space of all processes.
There is big confusion as how to install global hook and discussion about that falls beyond a scope of this forum.
We have two different kinds of hooks system-wide (global) or thread specific.
WH_MOUSE hook can be both.
If you install hook in exe module and pass thread ID it will filter messages for that thread only. It stops monitoring if you are outside of thread window, and continues when mouse is back over this window.
If you pass module handle not a thread ID, it will filter messages for local thread, but as soon as you leave window of that thread, a hook you install will be disconnected from a chain.
But you have another choice: window NT introduced so called low level hooks: WH_MOUSE_LL and WH_KEYBOARD_LL. They are both global only; therefore after installing WH_MOUSE_LL hook you will be able to catch all mouse messages for all threads from the desktop.
Last edited by JohnCz; April 19th, 2004 at 03:35 PM.
There are only 10 types of people in the world: Those who understand binary and those who do not.
What I mean by 'another region' is: the window the mouse is moving over is divided up into application-specific regions (really just rectangles at different co-ordinates). When the mouse moves from one of these regions to another, a new menu should popup. It works AFTER the first time, but not ON the first time. Does that make it more clear?
So, because of this, I am assuming I only need to use thread-specific hooks ie: I don't care about what the mouse is doing in any other application window apart from my own. The documentation I was reading, however, seemed to suggest that I needed to use a DLL for ANY WH_MOUSE filter function.... but it doesn't sound like it from your post.....
I am still not receiving any WM_MOUSEMOVE messages the first time I set the mouse hook (WH_MOUSE).
I tried using a WH_MOUSE_LL hook instead (as JohnCz suggested), but I cannot compile - WH_MOUSE_LL is an unknown identifier. I am using Win2000 SP4. I have tried include "winuser.h" and "windows.h" but still no luck.
Any suggestions?
thanks,
EM
Last edited by Emster; April 29th, 2004 at 02:22 AM.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.