Win32 C ++ ListView WM_CONTEXTMENU问题

问题描述

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

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

来自MS documentation

DefWindowProc在处理WM_RBUTTONUP或WM_NCRBUTTONUP消息时或在用户键入SHIFT + F10时,会生成WM_CONTEXTMENU消息。当用户按下并释放VK_APPS键时,也会生成WM_CONTEXTMENU消息。

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

当我将RMB放到ListView外面并放到里面时,上下文菜单仍然出现,并且从调用堆栈中可以看到最后一条消息是0x0205WM_RBUTTONUP

不确定我的代码中是否有错误或不清楚。谢谢。

解决方法

WM_RBUTTON(DOWN|UP)自己的WM_CONTEXTMENU而不是依靠lParam消息来确定鼠标坐标,而是为您提供生成{{1}的消息的鼠标屏幕坐标}。如果这些坐标不是您期望的坐标,则可以使用WM_CONTEXTMENU代替,它将在生成GetMessagePos()时报告屏幕坐标。无论哪种方式,您都可以使用WM_CONTEXTMENUScreenToClient()将屏幕坐标转换为ListView客户端坐标。

只要确保您还处理用户通过键盘输入而不是单击鼠标来调用弹出菜单的情况。在这种情况下,MapWindowPoints()的{​​{1}}将带有屏幕坐标lParam,您可以使用WM_CONTEXTMENU或在ListView中查询其选定项目的位置。 [x=-1,y=-1]根据需要,然后使用LVM_GETITEMPOSITIONLVM_GETITEMRECT将该位置转换为屏幕坐标,然后在该屏幕位置显示弹出菜单。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...