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!