在MFC中,双击鼠标事件会触发以下消息序列
- WM_LBUTTONDOWN
- WM_LBUTTONUP
- WM_LBUTTONDBCLK
- WM_LBUTTONUP
所以,回应 WM_LBUTTONDBCLK 消息允许你检测双击。但是,如果我只想检测单击,我该如何区分它呢?
但仅仅查看WM_LBUTTONUP消息是不够的,因为它可能是单击,也可能是双击的第一次点击。
我该如何成功识别只有单击?
在MFC中,双击鼠标事件会触发以下消息序列
所以,回应 WM_LBUTTONDBCLK 消息允许你检测双击。但是,如果我只想检测单击,我该如何区分它呢?
但仅仅查看WM_LBUTTONUP消息是不够的,因为它可能是单击,也可能是双击的第一次点击。
我该如何成功识别只有单击?
请允许我称这些事件为“鼠标弹起”和“鼠标按下”。我的MFC有点生疏。最近有个叫.NET的东西最近一直搞乱我的术语 ;)
短篇小说:你不只是想了解鼠标点击。你需要更多。
长故事
尽管这听起来有些违反直觉,但似乎仅仅想要一个鼠标点击是相当罕见的。通常情况下,您会想在鼠标按下时执行一些处理,并在鼠标松开时进行进一步处理。诀窍在于,仅仅跟踪鼠标松开消息是不够的:鼠标按下可能没有发生在您的窗口中。那么您认为这是有效的点击吗?特别是考虑到鼠标按下处理(例如选择某个项目)没有发生。
进一步推理,你不应该依赖于在处理鼠标下降后接收鼠标抬起:用户可能已经移动了鼠标并在其他地方释放了按钮(考虑拖放),在这种情况下,你本来不会收到鼠标抬起的事件...除非在MouseDown时捕获鼠标,以确保你获取了鼠标事件,直到鼠标抬起,即使鼠标离开你的窗口。
总的来说,你要跟踪鼠标按下,捕获鼠标,当你收到鼠标抬起时,只需检查是否拥有捕获。如果没有,鼠标可能是双击(没有第二次鼠标按下)或鼠标按下发生在其他地方,因此你可能不关心此鼠标抬起。
总之: 没有鼠标单击消息是因为您不能很远地使用它:您需要处理更多的消息并实现更多的机制。
哦!如果您正在处理一个已经处理所有这些项目和选择的控件,例如列表视图,那么它很有可能会提供类似的自定义通知,如项目激活或项目选择已更改。
我刚刚在Delphi中尝试了这个,行为是一样的:即使发生了双击,两次单击事件中的第一次后面仍然会发出一个单击事件。
我使用定时器解决它,它的工作原理是:
bDbl
to true
)bDbl==false
bDbl==true
(and reset bDbl
)我将定时器的间隔设置为 GetDoubleClickTime
返回的时间。
MSDN说:
The GetDoubleClickTime function retrieves the current double-click time for the mouse. A double-click is a series of two clicks of the mouse button, the second occurring within a specified time after the first. The double-click time is the maximum number of milliseconds that may occur between the first and second click of a double-click.
如果定时器恰好触发,则会发出真正的点击声。在我的情况下,双击间隔为500毫秒,因此任何“真正的点击”都会延迟这么长时间。
在 WM_LBUTTONUP 之前,您可以检查 WM_LBUTTONDOWN 是否被调用超过一次。在实践中,Windows 会为您执行此操作,即如果您收到 WM_LBUTTONDBCLK,则很容易不会收到 WM_LBUTTONUP。
您可以使用PreTranslateMessage()函数来计算消息的数量,当它们出现时。如果您只收到与单击相对应的鼠标消息,并且已经超过了系统配置的双击时间,您可以安全地假设这是一个单击。
据我所知,目前没有办法在发生时知道情况,这很有道理——在时间到期之前,无法知道是否会发生第二次点击。
那有点棘手。
我将检测 WM_LBUTTONDOWN 和 WM_LBUTTONUP 组合,将该事件存储在某个地方并设置一个大约一秒钟的超时。如果在超时期间没有 WM_LBUTTONDBCLK,则表示您进行了单击。
这可能意味着您需要运行另一个线程,但我认为您可以通过一个线程完成它。
我认为解决方法是在第一次点击后启动定时器,然后在下一次即时点击后检查经过的时间,这将告诉你它是单击还是双击。
你通常会查看 @MLButtonUp,并且同一个鼠标按钮上不会同时拥有单击和双击行为。