响应双击消息的时候,总是会先响应单击消息,然后再执行双击事件的代码。如果我们编制的程序需要单击、双击时实现不同的功能,这样就很不方便了。我google了下,网上主要就是两种思路。一是,双击时先回滚撤消单击的事件。还有就是在定时器里面对时间进行判断,如果超过指定时间就执行单击代码,否则就是执行双击的代码。

不过这样做都很麻烦!有一种比较简便的办法是:在单击事件中,截获windows消息,用一个死循环检测截获的消息。如果是双击消息就直接返回,如果超过指定的时间就break跳出死循环,执行单击事件的逻辑代码。

代码如下:

void CXXXXX::OnClick()
{
DWORD dwStart = GetTickCount();
 
MSG msg;
while(1)//循环检索消息队列
{
if(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
 
if(msg.message == NM_DBLCLK)
return;
}
 
DWORD dwEnd = GetTickCount();
if(dwEnd - dwStart > 200)
break;
}
 
//你的逻辑代码如下:
// ……
// ……
}

PeekMessage为一个消息检查线程消息队列,并将该消息(如果存在)放于指定的结构,这里用来获取消息队列中的消息,记录到MSG结构体的变量msg中。

TranslateMessage将虚拟键消息转换为字符消息

DispatchMessage分发一个消息给窗口程序

GetTickCount就是系统运行时间,以ms为单位,通过一前一后的比较,如果大于指定的时间200ms就退出循环。这时对外的效果就表现为单击。

当然200ms也可以改为用GetDoubleClickTime得到系统的双击速度,不过如果这个速度比较慢的话, 单击、双击效果就不太好了!表现就是单击了过几秒才会反应~ 所以还是推荐用固定的时间,比如200ms、300ms.

在双击事件里面就不需要再额外添加代码了,只要把单击事件的代码弄成上面那样就行了。