Raymond Chen 2004年10月15日
Windows将单击转换为双击机制的逻辑后果
首先,我建议您查阅 MSDN 关于鼠标点击的文档,因为这是我们讨论的起点。我假设您已经熟悉了将单击转换为双击的基本机制。
在您阅读了文档之后,让我们来探讨一下该机制的一些逻辑后果,以及它对您设计用户界面的意义。
有些人在设计双击操作时,希望其与单击操作完全不同。他们想知道是否能够抑制双击序列中的第一个WM_LBUTTONDOWN消息。
当然,这需要具备预知未来的能力。当鼠标按钮首次按下时,窗口管理器无法预知是否会有后续的点击,用户往往也无法确定。因此,窗口管理器会发出一个WM_LBUTTONDOWN消息,然后等待后续操作。
假设您是一个程序,您希望继续采用这种设计,即双击操作与单击操作无关。您应该如何处理呢?
一种方法是,在接收到WM_LBUTTONDOWN消息时不立即执行任何操作,而是设置一个计时器,在GetDoubleClickTime()
毫秒后触发。
如果在该时间段内收到WM_LBUTTONDBLCLK消息,则确实是一个双击操作。如果没有收到,则可以认为是一个单击操作,尽管响应可能稍晚一些。
这种“稍作等待”的技术在您没有双击操作,但第二个点击与第一个点击结合可能会引起问题时也是必要的。为什么?因为许多用户习惯于双击一切。
以下是一些应用“延迟操作以避免第二个点击”的场景:
void CALLBACK DelayedSingleClick(HWND hwnd, UINT, UINT_PTR id, DWORD)
{
KillTimer(hwnd, id);
MessageBeep(MB_OK);
}
void OnLButtonDown(HWND hwnd, BOOL fDoubleClick,
int x, int y, UINT keyFlags)
{
if (fDoubleClick) {
KillTimer(hwnd, 1);
MessageBeep(MB_ICONASTERISK);
} else {
SetTimer(hwnd, 1, GetDoubleClickTime(),
DelayedSingleClick);
}
}
HANDLE_MSG(hwnd, WM_LBUTTONDOWN, OnLButtonDown);
HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK, OnLButtonDown);
由于我们正在处理双击操作,我们需要启用它们:
wc.style = CS_DBLCLKS;
当您运行这个程序时,在客户端区域尝试点击和双击。请注意,程序会等待您的双击超时时间过后才对单击做出反应,因为它需要确定您是否打算进行第二次点击,从而完成一个双击操作而非单击。
在下一次的讨论中,我们将探讨双击之外的点击操作。