[英]Win32 C++ ListView WM_CONTEXTMENU Issue
I have a ListView with which I'd like to use a context menu that changes depending on selection.我有一个 ListView,我想用它来使用根据选择而变化的上下文菜单。 I'm making sure that I'm first able to display a menu when the right mouse button has been released (as per normal context menu behaviour).
我确保在释放鼠标右键时我首先能够显示菜单(根据正常的上下文菜单行为)。
In my ListView WNDPROC
I'm using WM_CONTEXTMENU
to display the context menu.在我的 ListView
WNDPROC
我使用WM_CONTEXTMENU
来显示上下文菜单。 The menu however is displayed at the location the cursor began the selection, not at the end.然而,菜单显示在光标开始选择的位置,而不是最后。
From the MS documentation :从MS 文档:
DefWindowProc generates the WM_CONTEXTMENU message when it processes the WM_RBUTTONUP or WM_NCRBUTTONUP message or when the user types SHIFT+F10.
DefWindowProc 在处理 WM_RBUTTONUP 或 WM_NCRBUTTONUP 消息或用户键入 SHIFT+F10 时生成 WM_CONTEXTMENU 消息。 The WM_CONTEXTMENU message is also generated when the user presses and releases the VK_APPS key.
当用户按下并释放 VK_APPS 键时,也会生成 WM_CONTEXTMENU 消息。
When I inspect the call stack, with a breakpoint in WM_CONTEXTMENU
, I see that the message sent prior to WM_CONTEXTMENU
was 0x0204
or WM_RBUTTONDOWN
containing the coordinates of the cursor at this time.当我检查调用堆栈,在断点
WM_CONTEXTMENU
,我看到该消息发送之前WM_CONTEXTMENU
是0x0204
或WM_RBUTTONDOWN
包含光标的坐标在这个时候。 This probably explains the menu location issue, but why would this be happening?这可能解释了菜单位置问题,但为什么会发生这种情况?
When I hold the RMB down outside of the ListView and release it inside, the context menu still appears and I can see from the call stack that the last message was 0x0205
or WM_RBUTTONUP
.当我在 ListView 之外按住 RMB 并在里面释放它时,上下文菜单仍然出现,我可以从调用堆栈中看到最后一条消息是
0x0205
或WM_RBUTTONUP
。
Not sure whether I have something wrong in my code, or I'm not understanding something.不确定我的代码是否有问题,或者我不明白。 Any help on this issue would be greatly appreciated, thanks.
对这个问题的任何帮助将不胜感激,谢谢。
Rather than relying on the WM_RBUTTON(DOWN|UP)
messages to determine the mouse coordinates, the WM_CONTEXTMENU
's own lParam
gives you the mouse's screen coordinates of the message that generated the WM_CONTEXTMENU
. WM_RBUTTON(DOWN|UP)
消息不是依靠WM_RBUTTON(DOWN|UP)
消息来确定鼠标坐标, WM_CONTEXTMENU
自己的lParam
为您提供生成WM_CONTEXTMENU
的消息的鼠标屏幕坐标。 If those coordinates are not what you are expecting, you can use GetMessagePos()
instead, which will report the screen coordinates at the time WM_CONTEXTMENU
was generated.如果这些坐标不是您所期望的,您可以改用
GetMessagePos()
,它会报告生成WM_CONTEXTMENU
时的屏幕坐标。 Either way, you can then convert the screen coordinates into ListView client coordinates using ScreenToClient()
or MapWindowPoints()
.无论哪种方式,你就可以将屏幕坐标转换为使用ListView的客户坐标
ScreenToClient()
或MapWindowPoints()
Just be sure you also handle the case where the popup menu is being invoked by the user via keyboard input rather than mouse click.请确保您还处理了用户通过键盘输入而不是鼠标单击调用弹出菜单的情况。 In that case, the
lParam
of WM_CONTEXTMENU
will carry the screen coordinates [x=-1,y=-1]
, and you can query the ListView for the position of its selected item(s) using LVM_GETITEMPOSITION
or LVM_GETITEMRECT
as needed, then convert that position to screen coordinates using ClientToScreen()
or MapWindowPoints()
, and then display the popup menu at that screen location.在这种情况下,
WM_CONTEXTMENU
的lParam
将携带屏幕坐标[x=-1,y=-1]
,您可以根据需要使用LVM_GETITEMPOSITION
或LVM_GETITEMRECT
查询 ListView 其所选项目的位置,然后转换使用ClientToScreen()
或MapWindowPoints()
将该位置转换为屏幕坐标,然后在该屏幕位置显示弹出菜单。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.