Win32 C++ ListView WM_CONTEXTMENU 问题

Win32 C++ ListView WM_CONTEXTMENU Issue

我有一个 ListView,我想在其中使用根据选择而变化的上下文菜单。我正在确保在释放鼠标右键时首先能够显示菜单(按照正常的上下文菜单行为)。

在我的 ListView WNDPROC 中,我使用 WM_CONTEXTMENU 来显示上下文菜单。然而,菜单显示在光标开始选择的位置,而不是结束处。

来自MS documentation

DefWindowProc generates the WM_CONTEXTMENU message when it processes the WM_RBUTTONUP or WM_NCRBUTTONUP message or when the user types SHIFT+F10. The WM_CONTEXTMENU message is also generated when the user presses and releases the VK_APPS key.

当我检查调用堆栈时,在 WM_CONTEXTMENU 中设置了一个断点,我看到在 WM_CONTEXTMENU 之前发送的消息是 0x0204WM_RBUTTONDOWN 包含坐标此时的光标。这可能解释了菜单位置问题,但为什么会发生这种情况?

当我在 ListView 外部按住人民币并在内部释放它时,上下文菜单仍然出现,我可以从调用堆栈中看到最后一条消息是 0x0205WM_RBUTTONUP

不确定我的代码是否有问题,或者我不理解某些东西。非常感谢对此问题的任何帮助,谢谢。

不是依靠 WM_RBUTTON(DOWN|UP) 消息来确定鼠标坐标,WM_CONTEXTMENU 自己的 lParam 为您提供生成 [= 的消息的鼠标屏幕坐标11=]。如果这些坐标不是您所期望的,您可以改用 GetMessagePos(),它将报告生成 WM_CONTEXTMENU 时的屏幕坐标。无论哪种方式,您都可以使用 ScreenToClient()MapWindowPoints().

将屏幕坐标转换为 ListView 客户端坐标

请确保您还处理了用户通过键盘输入而不是鼠标单击来调用弹出菜单的情况。在这种情况下,WM_CONTEXTMENUlParam 将携带屏幕坐标 [x=-1,y=-1],您可以使用 LVM_GETITEMPOSITION 或查询 ListView 以获取其所选项目的位置LVM_GETITEMRECT 根据需要,然后使用 ClientToScreen()MapWindowPoints() 将该位置转换为屏幕坐标,然后在该屏幕位置显示弹出菜单。