如何在 Windows 中以编程方式选择弹出菜单项?

发布于 2024-07-09 13:53:32 字数 391 浏览 7 评论 0原文

我有一个应用程序,我正在为其编写一个小向导。 它通过将鼠标移动到适当的按钮、菜单并单击它们来自动化应用程序的一小部分,以便用户可以观看。

到目前为止,它将鼠标移动到树项目并发送右键单击。 通过 TrackPopupMenu 弹出一个菜单。 接下来,我将鼠标移动到弹出菜单上的相应项目。 我不知道如何选择菜单项。

我尝试过将左键单击发送到菜单的所有者窗口,尝试将 WM_COMMAND 发送到菜单的所有者等。没有任何效果。

我想菜单本身就是一个窗口,但我不知道如何从我拥有的 HMENU 中获取它的 HWND。

关于如何在单击弹出菜单时发送消息有什么想法吗?

PS 我使用单独的线程来驱动鼠标并发布消息,因此 TrackPopupMenu 同步没有问题。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

等数载,海棠开 2024-07-16 13:53:32

我没有找到完美的方法来做到这一点,但以下方法效果很好:

//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;

右键单击树项时调用上述函数。 下面
代码在单独的线程中运行以进行单击

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);
}

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);
}
清音悠歌 2024-07-16 13:53:32

我希望您可以通过调用 SendInput。 将鼠标移到菜单所在的位置,然后单击。

您可能需要查看 WH_JOURNALPLAYBACK 挂钩。 我认为它的设计目的正是您似乎想要手动执行的操作。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文