DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 2 of 2

Thread: Handle of context menu

  1. #1
    Juergen Thuemmler Guest

    Handle of context menu

    Hi *.*,

    using a CWP-Hook and evaluating the WM_INITMENUPOPUP message, I get the
    handle of the popup menu in wParam. But sometimes, no WM_INITMENUPOPUP
    message is sent, but only WM_CONTEXTMENU.
    Sample: Win2K, device manager, SysTreeView32, right mouse click.
    Then wParam is the window handle where the mouse was clicked; a menu handle
    is not given.
    The window structure looks as follows:
    Class\Caption/Text (in german)
    mmcmainframe\geräte-manager
    mdiclient\notext
    mmcchildfrm\geräte-manager auf lokalem computer
    afxframeorview42u\notext
    afxframeorview42u\notext
    systreeview32\notext

    When I call hmen = GetMenu(hwnd) for each of these windows, I'll get a
    nonzero value except of the first and last window, but checking this value
    using IsMenu(hmen) always returns False :-(.
    How can I get the handle of the Context Menu???

    Juergen.




  2. #2
    Join Date
    Jan 2007
    Posts
    1

    reply to Getting Context Menu Handle

    Bit late to post reply for this now [sorry Juergen]... I was asking the same question a while ago about obtaining context menu handle, and it took me several days to figure it out because i couldn't find a ready answer on the net, so I want to post something that might be of help to future googlers... Here we go:


    I assume you really want the context menu handle just to be able to programmatically select a menu item from a popup/context menu. Actuallly it turns out that the menu handle is not necessary at all. Try these steps:

    1. Use Spy++ tool included in Visual Studio to "Log Messages" on all windows. (very important to select "All-Window" because menu commands may be addressed not the the window we would expect, but to one of its ancestors.) Filter out all other messages other than WM_COMMAND.

    2. Open up the context menu (you will see nothing yet on the msg log), open any submenus you need, then select the menuitem you want. Now, there should be one line of WM_COMMAND in the log. This is the command that selects that particular menu item. The wparam and lparam values are always the same, only the handle of the reciepient handle changes with each program run. So we need to obtain that handle programmatically. There are different ways to do this, the way i use is:

    3. Note down the handle of the reciepient above. Make sure not to close the target window during the following. I use the freely downloadable WinSpy because I find it easier to follow trees of windows using WinSpy than Spy++. Using WinSpy, starting from the top level window of the target application, expand each layer of windows until you find the window handle noted above. Then note down the ancestors lineage until the top window. (Note: the very top of the application tree is not actually a window.)

    4. Use FindWindow (..) API function to get the handle of the top level window. Then FindWindowEx (..) repeated to trace its children until you get the handle to the window you want. (Note. FindWIndowEx() searches only one level of children, so repeated calls is necessary.) For multiple children of the same class and name, you need to call FindWIndowEx (..) again modifying its IndexAfter parameter.

    5. Finally send the same message you see above, WM_COMMAND with the same wparam and lparam using SendMessage(..) API function using the handle you just found.


    For more information, refer to Petzold's "Programming Windows 5th ed", chapter10, Menus. I figured out the above only after reading this section a couple of times. Also, reading MSDN documentation on WM_COMMAND and the API functions used above will help to understand what to put in the parameters.

    The code for this in C# console application would be something like this:

    using System.Runtime.InteropServices;

    static void Main(string[] args)
    {
    int i = Win32.FindWindow(null, "WindowCaption";
    i = Win32.FindWindowEx(i,0, "#32770", null);
    i = Win32.FindWindowEx(i,0, "AfxOleControl42", null);
    i = Win32.FindWindowEx(i,0, "AfxFrameOrView42", null);
    Console.WriteLine("Target window handle: " + i);
    Win32.SendMessage (i, 0x0111, 0x000080B7, 0);
    //0x0111 stands for for WM_COMMAND
    }

    ...

    public class Win32
    {
    [DllImport("user32.dll")]
    public static extern int FindWindow (string lpClassName, string lpWindowName);

    [DllImport("user32.dll")]
    public static extern int FindWindowEx (int hwndParent, int hwndChildAfter, string strClassName, string strWindowName);

    [DllImportAttribute ("user32.dll")]
    public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);
    }

    Note: If you really need to obtain the handle of the context menu, try refering to "Win32 GUI Test" open-source source code, that contains an implementation of their GetPopupHandle() function. Basically they hook the window and simulate right button click and somehow obtain the handle... (I only skimmed through the code so I don't understand it fully)

    That's all, I hope that helps... Good luck!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center