2

I have an app that I'm writing a little wizard for. It automated a small part of the app by moving the mouse to appropriate buttons, menus and clicking them so the user can watch.

So far it moves the mouse to a tree item and sends a right-click. That pops up a menu via TrackPopupMenu. Next I move the mouse to the appropriate item on the popup menu. What I can't figure out is how to select the menu item.

I've tried sending left-clicks to the menu's owner window, tried sending WM_COMMAND to the menu's owner, etc. Nothing works.

I suppose the menu is a window in and of itself, but I don't know how to get the HWND for it from the HMENU that I have.

Any thoughts on how to PostMessage a click to the popup menu?

PS I'm using a separate thread to drive the mouse and post messages, so no problems with TrackPopupMenu being synchronous.

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
DougN
  • 4,407
  • 11
  • 56
  • 81

2 Answers2

2

I didn't find a prefect way to do it, but the following works pretty well:

//in my case, the menu is a popup from a tree control created with:
CMenu menu;
menu.CreatePopupMenu();
//add stuff to the menu...
pTreeCtrl->SetMenu(&menu);
m_hMenu = menu.GetSafeHmenu();
CPoint  pt;
GetCursorPos(&pt);
menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, pt.x, pt.y, _pTreeCtrl);
menu.Detach();
m_hMenu = NULL;

The above function was called on a right-click of the tree item. The below code gets run in a separate thread to do the click

CRect rc;
GetMenuItemRect(pTreeCtrl->GetSafeHwnd(), m_hMenu, targetMenuItemIndex, &rc);
if(FALSE == rc.IsRectEmpty())
{
   CPoint target = rc.CenterPoint();
   //this closes the menu
  ::PostMessage(pTreeCtrl->GetSafeHwnd(), WM_CANCELMODE, 0, 0);
  DestroyMenu(m_hMenu);
  m_hMenu = NULL;
  //now simulate the menu click
  ::PostMessage(pTreeCtrl->GetSafeHwnd(), WM_COMMAND, targetMenuItemID, 0);
}
DougN
  • 4,407
  • 11
  • 56
  • 81
1

I expect you could generate the necessary click messages by calling SendInput. Move the mouse over where the menu is, and then click.

You might want to take a look at the WH_JOURNALPLAYBACK hook. I think it's designed to do exactly what you seem to be trying to do manually.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467