在MFC中检测单击鼠标

时间:2009-02-03 16:18:50

标签: user-interface winapi visual-c++ mfc

在MFC中,双击鼠标单击事件会触发以下消息序列

  • WM_LBUTTONDOWN
  • WM_LBUTTONUP
  • WM_LBUTTONDBCLK
  • WM_LBUTTONUP

因此,响应 WM_LBUTTONDBCLK 消息可以检测到双击。但如果我只是想检测一次单击如何区分它?

但仅仅查看 WM_LBUTTONUP 消息是不够的,因为它可能是单击,也可能是双击的第一次点击。

如何才能成功识别单击?

7 个答案:

答案 0 :(得分:10)

(请允许我将这些事件称为Mouse Up和Mouse Down。我的MFC有点生疏。而且有一些名为.NET的东西最近弄乱了我的术语; - )

短篇小说:您不只是想了解鼠标点击。你需要更多。

长篇故事

虽然这是违反直觉的,但似乎只是想要鼠标点击是相当罕见的。大多数情况下,您需要在Mouse Down上执行一些处理,并在Mouse Up上进行一些进一步处理。诀窍是仅仅跟踪Mouse Up消息是不够的:在窗口中可能没有发生鼠标停用。你认为这是一个有效的点击吗?特别是考虑到鼠标按下处理(例如选择项目)没有发生。

进一步推理,你不应该依赖于在处理鼠标后接收鼠标:用户可能已经移动了鼠标并在其他地方释放了按钮(想想拖拉),在这种情况下,你不接收MouseUp事件...除非您在MouseDown上捕获鼠标以确保鼠标事件达到Mouse Up,即使鼠标离开窗口也是如此。

总而言之,您最终会跟踪Mouse Down,捕获鼠标,当您收到Mouse Up时,只需检查您是否拥有捕获。如果没有,鼠标要么双击(没有第二个鼠标按下),要么鼠标在其他地方发生,因此你很可能不关心这个鼠标。

总结:没有MouseClick消息只是因为你不会走得太远:你需要处理更多的消息并实现更多的机制。

哦!如果您处理已经处理了所有这些项目和选择内容的现有控件(例如列表视图),则可能会提供类似的自定义通知,例如项目激活或项目选择已更改。

答案 1 :(得分:1)

我刚刚在Delphi中尝试过这种方法,行为是一样的:即使发生双击,也会在两个中的第一个之后发出单击事件。

我使用计时器解决了它,它的工作原理如下:

  • 停用WM_LBUTTONDBLCLK上的计时器(并将bDbl设置为true
  • 如果bDbl==false
  • ,则在WM_LBUTTONUP上激活计时器 如果bDbl==true(并重置bDbl),则
  • 停用WM_LBUTTONUP

我将计时器的间隔设置为GetDoubleClickTime返回的时间。

MSDN说:

  

GetDoubleClickTime函数   检索当前的双击   鼠标的时间。双击即可   两次点击鼠标   按钮,第二个发生在一个   第一个之后的指定时间。该   双击时间是最大值   可能发生的毫秒数   在第一次和第二次点击之间   双击。

如果计时器恰好点火,那么你就是真正的点击。在我的情况下,双击间隔是500毫秒,所以任何“真正的点击”将延迟这么久。

答案 2 :(得分:0)

你可以检查在WM_LBUTTONUP之前没有多次调用WM_LBUTTONDOWN。在实践中,Windows会为您执行此操作,因为如果您获得WM_LBUTTONDBCLK,则往往不会获得WM_LBUTTONUP。

答案 3 :(得分:0)

您可以使用PreTranslateMessage()来计算出现的消息。如果您只收到与单击相对应的鼠标消息,并且系统配置的双击时间已过期,您可以放心地假设只需单击一次。

据我所知,没有办法知道这种情况正在发生,这是有道理的 - 直到时间到期,没有办法知道第二次点击是否来临

答案 4 :(得分:0)

这有点棘手。

我会检测到WM_LBUTTONDOWN& WM_LBUTTONUP组合,将该事件存储在某处并设置超时一秒左右。如果在超时期间没有WM_LBUTTONDBCLK,则只需单击一下即可。

这可能意味着你需要运行另一个线程,但我认为你可以用一个线程完成它。

答案 5 :(得分:0)

我认为解决方案是在第一次点击后启动计时器。然后检查下次立即点击后经过的时间,这将告诉您是单击还是双击。

答案 6 :(得分:-2)

您通常会查看@MLButtonUp,并且您不会在同一个鼠标按钮上单击和双击行为。