Detecting a single mouse click in MFC

17,182

Solution 1

(Please allow me to call these events Mouse Up and Mouse Down. My MFC is a little rusty. And there's this stuff called .NET who's been messing up my terminology lately ;-)

Short story: You don't simply want to know about Mouse Click. You need more.

Long story:

Although this is counter-intuitive, it appears that simply wanting a mouse-click is fairly uncommon. Most often, you'll want to perform some processing on Mouse Down and do some further processing on Mouse Up. The trick is that simply tracking Mouse Up messages is not enough: Mouse Down may not have happened in your window. Do you consider it a valid click then? Especially considering that the Mouse Down processing (such as selecting an item) did not occur.

Going further up the reasoning, you should not rely on receiving a Mouse Up after you processed Mouse Down: User may have moved the mouse and released the button somewhere else (think drag'n'drop), in which case, you don't receive the MouseUp event... unless you capture the mouse on MouseDown to make sure you get mouse event up to Mouse Up even if the mouse left your window.

All in all, you end up tracking Mouse Down, capture the mouse and when you receive Mouse Up, just check if you own the capture. If not, the mouse was either double-clicked (no 2nd mouse down) or Mouse Down happened somewhere else hence you most likely don't care about this Mouse Up.

In conclusion: There's no MouseClick message simply because you wouldn't go very far with it: You need to handle more messages and implement more mechanics anyway.

Oh! And if your dealing with an existing control which already handles all this items and selection stuff, such as a listview, chances are it provides with a similar custom notification such as Item Activate or Item Selection Changed.

Solution 2

I just tried this in Delphi, the behavior is the same: even when a double click is happening, a single click event is issued right after the first one of the two.

I solved it using a timer, which works like this:

  • deactivate timer on WM_LBUTTONDBLCLK (and set bDbl to true)
  • activate timer on WM_LBUTTONUP if bDbl==false
  • deactivate on WM_LBUTTONUP if bDbl==true (and reset bDbl)

I set the interval of the timer to the time returned by GetDoubleClickTime.

MSDN says:

The GetDoubleClickTime function retrieves the current double-click time for the mouse. A double-click is a series of two clicks of the mouse button, the second occurring within a specified time after the first. The double-click time is the maximum number of milliseconds that may occur between the first and second click of a double-click.

If the timer happens to fire then you have the real click. In my case the double click interval is 500ms, so any "real click" will be delayed this long.

Share:
17,182
Matt Warren
Author by

Matt Warren

Some of my code samples are available on github

Updated on June 07, 2022

Comments

  • Matt Warren
    Matt Warren almost 2 years

    In MFC a double-mouse click event triggers the following sequence of messages

    • WM_LBUTTONDOWN
    • WM_LBUTTONUP
    • WM_LBUTTONDBCLK
    • WM_LBUTTONUP

    So responding to the WM_LBUTTONDBCLK message allows you to detect a double-click. But if I just want to detect a single-click how to I distinguish it?

    But just looking at the WM_LBUTTONUP message isn't enough as it could be a single-click or it could be the first click of a double-click.

    How can I successfully identify just a single-click?