Can I differentiate between single and double clic

2019-08-02 17:06发布

问题:

I create my system tray icon using Shell_NotifyIcon and then trap its WM_LBUTTONDBLCLK notifications for when a user double-clicks the icon (I use it show a dialog window.) I also trap WM_RBUTTONDOWN notifications to show the context menu.

Now I'm thinking that it would be nice to show a context menu after a single left click. But how do I do that?

If I trap WM_LBUTTONDOWN and show my context menu it works fine. But then when someone double-clicks the icon, it first shows my context menu and then displays the dialog window. So I'm not sure how to overcome this?

EDIT: Here's my code:

NOTIFYICONDATA nid;
memset(&nid, 0, sizeof(nid));
nid.cbSize = sizeof(nid);
nid.hWnd = this->GetSafeHwnd();
nid.uID = TRAY_ICON_ID1;
nid.uFlags = NIF_ICON;
nid.uCallbackMessage = TRAY_NOTIFICATION_ID1;
nid.hIcon = ghIcon;

Shell_NotifyIcon(NIM_ADD, &nid);

and then:

ON_MESSAGE(TRAY_NOTIFICATION_ID1, OnTrayIconNotifications)

LRESULT OnTrayIconNotifications(WPARAM wParam, LPARAM lParam)
{
    UINT uID = (UINT)wParam;
    UINT uMouseMsg = (UINT)lParam;

    if(uID == TRAY_ICON_ID1)
    {
        switch(uMouseMsg)
        {
        case WM_RBUTTONDOWN:
            {
                //Show context menu
                //...
                int nChosenCmd = TrackPopupMenu(hMenu, 
                    TPM_RIGHTALIGN | TPM_TOPALIGN |
                    TPM_LEFTBUTTON | TPM_VERPOSANIMATION | 
                    TPM_HORNEGANIMATION | TPM_RETURNCMD,
                    x, y, 0, 
                    this->GetSafeHwnd(), NULL);
            }
            break;

        case WM_LBUTTONDBLCLK:
            {
                //Show dialog window
                CDialogBasedClass dlg(this);
                dlg.DoModal();
            }
            break;
        }
    }

    return 0;
}

回答1:

I suspect you will have to get smart about it.

In your WM_LBUTTONDOWN click handler, set a timer that expires after the system's double click time has elapsed. In your WM_LBUTTONDBLCLICK handler check if that timer is active and if it is, cancel it.

If the timer expires that means the user clicked your icon but did not go ahead and double-click it; that means it's time to show the context menu.



回答2:

Show context menu on WM_RBUTTONDOWN or WM_CONTEXTMENU. Regarding left button single and double click, correct design requires double-click handler as continuation of single click. For example, in Windows Explorer single click selects a file, and double click opens it. Single click handler always works before double click handler, and this should look natural. In your case I would show a menu on right click, and dialog on left click.

Solutions based on timers and delays create buggy and unreliable code.