CListCtrl中.双击时总是接收NM_CLICK + NM_DBLCLK

Jos*_*emi 1 c++ mfc double-click clistctrl visual-studio-2015

当我用鼠标双击时,我总是得到两条消息NM_CLICK然后NM_DBLCLK.为什么?

你知道我怎么能区分两者?

IIn*_*ble 7

当我用鼠标双击时,我总是得到两条消息NM_CLICK,然后是NM_DBLCLK.为什么?

简答:因为系统没有实现时间机器.

当您单击鼠标时,系统会生成NM_CLICK通知,因为它还不知道这是否是双击序列的开始.这允许应用程序立即响应鼠标单击事件,而无需等待双击超时到期.

要辨别单击和双击,您必须推迟NM_CLICK处理,直到您知道,它不是NM_DBLCLK序列的一部分.为此,在NM_CLICK处理程序中设置一个计时器,并从中取消计时器NM_DBLCLK.当计时器到期时,您知道没有NM_DBLCLK尾随,您可以继续处理单击.

以下应该给你一个想法,如何实现这个:

enum TimerId {
    TimerId_ListCtrlDblClk = 1
};


BOOL CMyDialog::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult ) {
    const NMHDR& hdr = *(const NMHDR*)lParam;
    switch ( hdr.code ) {
    case NM_CLICK:
        SetTimer( TimerId_ListCtrlDblClk, ::GetDoubleClickTime(), nullptr );
        *pResult = 0;
        return TRUE;

    case NM_DBLCLK:
        KillTimer( TimerId_ListCtrlDblClk );
        // Handle double-clicks here.
        *pResult = 0;
        return TRUE;

    default:
        break;
    }

    return CDialogEx::OnNotify( wParam, lParam, pResult );
}

void CMyDialog::OnTimer( UINT_PTR nIDEvent ) {
    if ( nIDEvent == TimerId_ListBoxDblClk ) {
        // If this timer expires, there is no NM_DBLCLK trailing the NM_CLICK.
        // Handle the regular NM_CLICK notification.
    }

    CDialogEx::OnTimer( nIDEvent );
}
Run Code Online (Sandbox Code Playgroud)

  • 注意事项 - 虽然此解决方案确实有所区别,但请确保您的UI行为对于单击行为是可接受的(即您的UI看起来很慢).请记住,在Windows鼠标配置中,"双击"延迟是用户可配置的,因此它可能比您在设备上测试的时间长.注意:通常,单次单击的默认行为在双击之前是可接受的,或者是无关紧要的(并且大多数时候需要)(例如,您想要双击选中的项目,这在单击期间发生处理程序). (3认同)