Pitfalls in handling the WM_CONTEXTMENU message

Date:September 21, 2004 / year-entry #342
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20040921-00/?p=37813
Comments:    29
Summary:Before we continue with our IContextMenu discussion, I need to take a little side trip and discuss the subtleties of the WM_CONTEXTMENU message. First, a correction to the existing header file: #undef HANDLE_WM_CONTEXTMENU #define HANDLE_WM_CONTEXTMENU(hwnd, wParam, lParam, fn) \ ((fn)((hwnd), (HWND)(wParam), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)), 0L) Apparently, HANDLE_WM_CONTEXTMENU was overlooked when the header file gained...

Before we continue with our IContextMenu discussion, I need to take a little side trip and discuss the subtleties of the WM_CONTEXTMENU message.

First, a correction to the existing <windowsx.h> header file:

#undef HANDLE_WM_CONTEXTMENU
#define HANDLE_WM_CONTEXTMENU(hwnd, wParam, lParam, fn) \
    ((fn)((hwnd), (HWND)(wParam), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)), 0L)

Apparently, HANDLE_WM_CONTEXTMENU was overlooked when the <windowsx.h> header file gained multimonitor support.

The second subtlety of the WM_CONTEXTMENU message is the recognition that context menus can be invoked from the keyboard, not just by the mouse. If you have a 104-key keyboard, you will probably have a menu key to the right of your space bar. (Laptop owners: You're on your own. Laptop keyboards are hardly standardized.) Alternatively, you can type Shift+F10 to get the same effect.

When the user invokes a context menu from the keyboard, the x and y coordinates are both -1. In this case, you should display the context menu for the currently-selected item (or items, if a multiple selection is active). If you miss this detail, then you will end up hit-testing against (-1, -1) and probably not find anything.

Okay, now that these remarks on the WM_CONTEXTMENU message are out of the way, we can return to our discussion of the IContextMenu interface next time.


Comments (29)
  1. Cooney says:

    Raymond, what was the original code doing? I’d like to know why mozilla (and many, many other apps) bork the context menu. Also, would this same thing show up with autocomplete windows?

  2. Scott says:

    Pressing that context menu key sure does expose some missed handling. For instance Lotus Notes just ignores it, and it has context menus everywhere from the mouse.

    Also quirky is that Explorer puts the context menu at the currently selected item’s location, while IE puts it at the top-left corner regardless of the item. Is there standard for that?

  3. Carlos says:

    is there standard for that?

    From the MSDN entry for WM_CONTEXTMENU:

    …then the x- and y-coordinates are -1 and the application should display the context menu at the location of the current selection rather than at (xPos, yPos).

    However, IE doesn’t have a selection most of the time, so that probably explains its behaviour.

  4. mschaef says:

    "However, IE doesn’t have a selection most of the time, so that probably explains its behaviour. "

    Perhaps a reasonable alternative would be to display the context menu under the mouse, if there’s no default selection?

    I can see that that might cause problems for users if the mouse is over some other app, though.

  5. Mike Dunn says:

    With multiple monitors, (-1,-1) is a valid coordinate, so you have to hope that your users don’t have a monitor that contains that point, and that they don’t r-click exactly at (-1,-1) ;)

  6. This exact same bug occurs in MFC. I tried to explain the issue to a Microsoft employee on the MFC news group but it would appear that Microsoft employee’s are incapable of admitting that bugs exist. It would be nice if there were a way of submitting bug reports to Microsoft without having to risk paying Microsoft PSS some huge amount of cash if they don’t agree that something is a bug.

    The thread is on groups.google.com here: http://tinyurl.co.uk/s3uw . I was trying to be polite and helpful in all my posts but the replies I got seems unhelpful and tried to avoid the issue (hiding a cast in a call to sprintf isn’t great).

  7. I’m forwarding this discussion to the VC libraries lead. He’s very interested in improving the libraries. His blog is http://blogs.msdn.com/martynl. It probably is too late for VS/Whidbey unless this has already been fixed.

  8. Raymond Chen says:

    I just checked with Andrew. There was a misunderstanding. He thought you were trying to debug your own program, not MFC itself. (And yes, there is a bug in the MFC bug database for this.)

  9. Thanks Raymond, Michael & Andy! Sorry if my last post here came across as being a little rude – sometimes it is frustrating to try and find the right place and way to report a bug. It seems like everything is sorted now – you have the bug in your database which is what I was hoping for and I have a work around that I can use for now.

  10. Jeff Parker says:

    Hmmm, Ok Raymond, I guess I am confused and more so now. Yesterday I asked if you were doing anything on the .net side of the context menu, but you said you knew nothing of windows forms. I figured hmm ok Context Menu’s mean something else to Raymond and not the thing I was thinking of. But today when I see this Yeah they are the same thing. Or am I still missing something. Forgive me if this sounds like a silly questions but what is different with the windows forms context menu and the context menu this series is on. Or is it just the .net side of windows forms context menu you are not familiar with? Which is understandable several areas of that go back into some unmanaged code which is undocumented which I am guessing is doing everything your talking about here for us in the framework.

  11. Saurabh Jain says:

    And to answer second question of Jonathan, you can use the MSDN product feedback center to report the bugs.

    http://msdn.microsoft.com/productfeedback

    Note that it currently only supports issues around VS 2005 beta.

  12. Jeff Parker says:

    Gotcha, will keep my trap shut wait to see this play out and see if the light bulb comes on making the connection. Thats where I am loosing the connection when .net is going to Unmanaged API calls to actually do the work.

    I also misinterpereted when you said windows forms. I guess I have always considered a "windows form" a Graphical UI despite what method you use to get it. Via .net, C, VB, VBA, VB Scripting. Kind of like I still refer any command line utility as a DOS utility, or console utility, command shell utility, even though command line utilities can be built with several different technologies as well. Yes, I know they are not DOS, but sometimes hard to give up the terms you have used for 15+ years so I will probably still call any command line app a DOS app for years yet to come.

  13. Scott says:

    I think you’re right. I was testing it by tabbing between links in IE, and they aren’t actually selected when you do that, just focused. (As opposed to Explorer, where the entries are properly selected.)

  14. John McCormick says:

    When using the mouse, the item that was actually clicked takes priority over the selection.

    Sometimes (in Explorer, for example) this means that the selection gets changed just before the context pop-up.

    It makes sense to me, especially if no selection is available, to instead use the currently focused item to determine what context menu should be shown. Is this not a recommended practice?

  15. Raymond Chen says:

    I’m dealing with Win32 context menus. I have no idea whether Windows Forms context menus are the same thing or not. That’s for you to figure out. Whether you’re missing something is up to you.

    It’s like someone saying, "In this talk, I’m going to discuss LEGO blocks," and someone else asking, "Is this the same as LEGO Mindstorms?" The first person replies, "I don’t know anything about LEGO Mindstorms".

    And then the first person gives their talk and then the second person says, "Hey, now I’m confused. You said you didn’t know anything about LEGO Mindstorms, but it sounds like they are the same thing. Or am I still missing something?"

    The first person is talking about LEGO blocks and doesn’t know anything about LEGO Mindstorms. If they two are related, then great! If not, then oh well. But asking the first person to clarify the relationship between the two isn’t going to help any because the first person *doesn’t know*.

  16. Andy Mortimer says:

    Hi,

    I don’t want to hijack your thread or cloud the issue under discussion here, but just to clarify the comments I made in http://tinyurl.co.uk/s3uw

    If you are experiencing a bug and it is crucial to your business, then follow the normal support procedures in order to create a break/fix support case with PSS. This is your quickest route to resolving the issue and perhaps obtaining a hotfix (though in the WM_MOUSEWHEEL case we have a workaround).

    If you just want to report a bug to ensure it is fixed in the next release of the product, then check that it has been fixed on the latest builds here

    http://lab.msdn.microsoft.com/vs2005/

    and submit your bug here

    http://lab.msdn.microsoft.com/productfeedback/

    A newsgroup discussion will not always get you the information you require as there is no guarantee that anyone reading it will be in a position to help you. However in the WM_MOUSEWHEEL discussion Jonathan got lucky and I was in a position to progress this. That is what "I have created a bug for this and it will be dealt with in due course" means.

    Apologies if my actions were unclear.

    Andy

  17. Frank says:

    The MSDN page on the WM_CONTEXTMENU Notification states that "The WM_CONTEXTMENU message is also generated when the user presses and releases the VK_APPS key".

    This seems not to be correct.

    It would mean that our application does not have to care about the VK_APPS key when it handles the WM_CONTEXTMENU notification. Instead, it seems we have to generate the WM_CONTEXTMENU ourselves when the user presses the VK_APPS key.

  18. Ben Hutchings says:

    Andy, Saurabh: I would like to use the MSDN product feedback centre, but submissions require a Passport. The terms of use for Passport say it’s for non-commercial use only. Since I only do Windows development for work, any bug reports I make would be done as part of my work. I’m currently querying this apparent conflict with Passport support but I wonder whether you have any advice. (Quite apart from that, I’m deeply unhappy about any agreement that says its terms can be changed by one party without notice. I don’t believe this is a valid clause under English or US law, but I feel it would be bad faith on my part to pretend to agree with it.)

  19. What if I have a bug that isn’t critical to my business (because I can hack around it) but I would like to see it fixed in some future version of Visual Studio? Are you saying that the links you provided are the correct place to submit bugs in the *current* version if Visual Studio even if I do not have access to the 2005 beta? If so the site does not make that clear. When I have previously spoken to PSS they have been very helpful but I do not want to risk wasting £600 or a support instance just to report something they might or might not agree is a bug.

    (and sorry for the thread hijacking)

    Jonathan

  20. Raymond Chen says:

    Note that this specific bug was correct code when it was originally written (and tested). It was the introduction of multiple monitors that broke it. So the OS is partly to blame for adding multiple monitor support and breaking old programs that assume mouse coordinates could never be negative.

    "Instead, it seems we have to generate the WM_CONTEXTMENU ourselves when the user presses the VK_APPS key."

    Yesterday’s program doesn’t process the VK_APPS key, yet when you press it the program gets a WM_CONTEXTMENU message. Your program (or perhaps a global hook on your system) must be doing something strange.

  21. <pointless-pedantic-argument>

    Weren’t mouse-wheels and multiple monitors introduced around the same time? The Microsoft web site claims the first Microsoft mouse to have a mouse wheel was made in 1996 and I think the first operating system to support multiple monitors was Windows 98. I don’t think there were any OS releases between 1996 and 1998 so I would expect Windows 98 was the first OS to have the wheel messages built-in. If so, that would mean that the person who added mouse wheel support to MFC could have know about multiple monitor issues (I am sure there is a flaw in this argument but I haven’t spotted it yet).

    Also, MFC is distributed with the Windows XP so it might be reasonable to expect that version to work correctly on multiple monitor systems but there is at least one multiple monitor bug. If you run WordPad on a screen with negative co-ords, floating toolbars can not be resized (not that anyone is going to be that bothered).

    </pointless-pedantic-argument>

  22. Raymond Chen says:

    Don’t forget Windows 95 OSR2 which came out in late 1996.

  23. mschaef says:

    "Don’t forget Windows 95 OSR2 which came out in late 1996. "

    This is ancient history, and not quite the same, but DOS 1 or 2 also had some limited support for multiple monitors, as long as one was an MDA and the other a CGA. It allowed you to say things like "mode co80" and "mode mono" to switch displays from the command prompt. Lotus 1-2-3 could display a graph on a CGA with the worksheet on the MDA, although it didn’t use any OS services to do it.

  24. As always, you are right (I knew there must have been a flaw somewhere in my argument).

  25. mschaef says:

    "What if I have a bug that isn’t critical to my business (because I can hack around it) but I would like to see it fixed in some future version of Visual Studio?"

    As long as the thread has already been hijacked, I can’t resist:

    In the open source community, this would be handled by fixing the bug yourself and submitting a patch to the maintainer.

    In contrast to getting a passport ID, hitting a website, submitting a bug request into some apparant void, hoping it gets read, living with the bug for a few years, and then hoping it gets prioritized high enough to be fixed in some later release (if the produce doesn’t get discontinued *cough*VB6*cough), the open source model seems much more developer friendly and likely to produce a quality product in the long run. (Not to mention that the availability of source would likely make it easier to debug in the first place.)

    You could argue that the rigorous testing and disciplined development of commercial software is going to produce a more reliable product, but given that this discussion is in the context of a bug, that’d be more than a little ironic.

    Of course, I (try to) sell software too…

  26. Shawn says:

    What a timely post. I’ve been working on an MFC app that contains a class I’ve derived from CTreeView. I’d like to pop a context menu on the WM_CONTEXTMENU message inside my control, however it looks like tree views are special when it comes to WM_CONTEXTMENU. I have to double-click the right button before one gets sent. Attaching Spy++ to Windows Explorer revealed the same thing, so I can only imagine that they have some other workaround coded into their source. Is there a reason for this behavior? An appropriate way to work around it? (I don’t want to hard code to right clicks in case the user has customized which button should pop the context menu).

    -Shawn

  27. Tim Dawson says:

    In .NET 1.0 and 1.1, the Windows Forms context menu is a wrapper around the standard Win32 menus, so their nuances apply there too.

    In .NET 2.0 the ContextMenu class is still there but the new recommendation is the ContextMenuStrip, which is a managed replacement for the Win32 menu that supports extra functionality more like the nicer Office-style menus seen in recent Microsoft software.

    As an author of a custom menu system component I’ve had to deal with positioning of context menus launched by the keyboard, and I’ve set the default to display at the centre of the control.

  28. LonTonG says:

    Ada post yang menarik di milis dotnet tentang event mouse click. Setiap kali kita meng-klik tombol kanan

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index