How to host an IContextMenu, part 5 – Handling menu messages

Date:September 27, 2004 / year-entry #350
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20040927-00/?p=37733
Comments:    2
Summary:One bug that was called out immediately in our first attempt at displaying the context menu to the user is that the Open With and Send To submenus don't work. The reason for this is that these submenus are delay-generated (which explains why they don't contain anything interesting when you expand them) and owner-drawn (which...

One bug that was called out immediately in our first attempt at displaying the context menu to the user is that the Open With and Send To submenus don't work.

The reason for this is that these submenus are delay-generated (which explains why they don't contain anything interesting when you expand them) and owner-drawn (which you can't notice yet because of the first problem, but trust me, they are).

This is where the IContextMenu2::HandleMenuMsg and IContextMenu3::HandleMenuMsg2 methods are used.

Historical note: IContextMenu2::HandleMenuMessage is on its own interface rather than being merged with the base interface IContextMenu because it was added late in Windows 95 development, so it was considered safer to add a derived interface than to make everybody who had been writing Windows 95 shell extensions go back and rewrite their code. IContextMenu3::HandleMenuMessage2 was added in Internet Explorer 4 (I think) when it became clear that the ability for a context menu extension to override the default message return value was necessary in order to support keyboard accessibility in owner-drawn context menus.

In a "real program", these two variables would be class members associated with the window, but this is just a sample program, so they are globals. When you write your own programs, don't use global variables here because they will result in mass mayhem once you get a second window, since both of them will try to talk to the interface even though only the window displaying the context menu should be doing so.

IContextMenu2 *g_pcm2;
IContextMenu3 *g_pcm3;

These two new variables track the IContextMenu2 and IContextMenu3 interfaces of the active tracked popup menu. We need to initialize and uninitalize them around our call to TrackPopupMenuEx:

      pcm->QueryInterface(IID_IContextMenu2, (void**)&g_pcm2);
      pcm->QueryInterface(IID_IContextMenu3, (void**)&g_pcm3);
      int iCmd = TrackPopupMenuEx(hmenu, TPM_RETURNCMD, pt.x, pt.y, hwnd, NULL);
      if (g_pcm2) {
        g_pcm2->Release();
        g_pcm2 = NULL;
      }
      if (g_pcm3) {
        g_pcm3->Release();
        g_pcm3 = NULL;
      }

And finally we need to invoke the HandleMenuMessage/HandleMenuMessage methods in the window procedure:

LRESULT CALLBACK
WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
    if (g_pcm3) {
        LRESULT lres;
        if (SUCCEEDED(g_pcm3->HandleMenuMsg2(uiMsg, wParam, lParam, &lres))) {
          return lres;
        }
    } else if (g_pcm2) {
        if (SUCCEEDED(g_pcm2->HandleMenuMsg(uiMsg, wParam, lParam))) {
          return 0;
        }
    }

    switch (uiMsg) {
    ....

In the window procedure, we ask the context menu whether it wishes to handle the menu message. If so, then we stop and return the desired value (if HandleMenuMsg2) or just zero (if HandleMenuMsg).

With these changes, run the scratch program again and observe that the Open With and Send To submenus now operate as expected.

Next time: Getting menu help text.


Comments (2)
  1. IContextMenu のホスト方法 – Shell

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