I have an application to log mouse clicks. I need a single log for each clicks. During double click, the mouse button generates a sequence of messages: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBCLK and WM_LBUTTONUP. So I am getting 4 logs for each double click. Since logs are handled with generating messages.
Is there any way to restrict the other logs and get the log of WM_LBUTTONDBCLK only.
Thanks in advance.
As you know, the Windows can't detect "double click" from first pressing. So, you should do this himself.
For example, at first single click you start timer (for example, upto 500 ms). In case the timer is over and double click hasn't been received you log single click. In other case you should log double click.
Related
I am using below code in my application's view on particular event to simulate a left mouse click.
SendMessage(WM_LBUTTONDOWN);
SendMessage(WM_LBUTTONUP);
Once this code executed a mouse drag view appears. How to avoid this drag view after simulating the mouse click?
When I monitored via SPY++ I got the both messages are sent like below,
WM_LBUTTONDOWN fwKeys: MK_LBUTTON xPos : 752 yPos:85
WM_BUTTONUP fwKeys:0000 xPos:752 yPos 85
I suspect the WM_LBUTTONUP message not sent properly.
What is the fwKeys : 0000 indicates?
Is there any think wrong in sendMessage of WM_LBUTTON up in the above code?
First of all, if that is your real code, you are "simulating" the mouse click improperly. There's more to a WM_LBUTTONDOWN or WM_LBUTTONUP than the message itself: there's data packed in the wParam and lParam values of the message.
You could easily see that if you had taken a second to look at the MSDN pages for WM_LBUTTONDOWN and WM_LBUTTONUP. They describe exactly what the wParam and lParam values mean in this context. And, by the way, this would also answer your question about the meaning of "fwKeys" in Spy++.
But really, if you need to simulate mouse events, then do it the right way: call the mouse_event function. It's whole purpose in life is to synthesize mouse events.
On to your other question: how to disable the drag view: it depends on what kind of control you're dealing with. For example, if you had a tree view control, then you could set the TVS_DISABLEDRAGDROP style on the control, as stated on MSDN. If you want to disable drag & drop for that control permanently, then set the flag when you create the control. If you only want to disable it temporarily, during your synthesized input operations, then that's a bit trickier - you can use CWnd::ModifyStyle to temporarily remove the TVS_DISABLEDRAGDROP but you will also need to add code to enable it again, after you finish sending your synthesized mouse movements and the control has finished processing them.
With all that said, what exactly are you trying to achieve? There may be an easier way to solve the problem that you are trying to address.
Thanks for all your answers and support.
I am working on a already developed application which requires this solution. Finally I found that the WM_LBUTTONDOWN handler was already defined in my view. This takes time to execute. Since I used SendMessage which posts message to a thread's message queue and return immediately, before the WM_LBUTTONDOWN finished, the next message WM_LBUTTONUP is called. So the WM_LBUTTONUP was failing.
I used PostMessage as below,
PostMessage(WM_LBUTTONDOWN);
PostMessage(WM_LBUTTONUP);
This resolves my problem.
I have a Windows application that registers one CALLBACK procedure that handles WM_HELP messages for the dialog, and one CALLBACK procedure that handles WM_LBUTTONUP messages for a custom button.
Now, when the user clicks the "?" button, then clicks the custom button, the help opens up as expected (on mouse down), BUT if the help window is not occluding the button, a WM_LBUTTONUP message is triggered as well for the custom button (on mouse up). This causes the button to trigger when the user was only asking for help.
Is there any way to stop the WM_LBUTTONUP message from being sent if the button press is for help?
EDIT: The custom button is implemented using a STATIC control. I believe this is because it needs to have an image and no border. So, it does not send BN_CLICKED notifications. In fact, it does not seem to trigger WM_COMMAND in the parent at all.
Thanks
This is normal. Be sure to use the button's BN_CLICKED notification to see the difference. Generated when the user clicks the button, not generated when the user uses the help cursor. The button still sees the normal button up/down messages so that's not a good trigger to detect a click. Extra bonus is that the button can now also be clicked with the keyboard (space bar).
A good class library takes care of these nasty little details.
A better way would be to create ? as a custom control with BS_CHECKBOX | BS_PUSHLIKE style and capture the mouse. After that you will get all the WM_LBUTTONDOWN message to this custom control and then you can use WindowFromPoint to get the window where the WM_LBUTTONDOWN happened and can send a custom notification to the parent window. The parent window can then show a the tooltip or open the help doc or discard it.
The advantage is, you create the control only once and you can use it in multiple places.
Okay, I fixed it by creating the custom button (static control) with the SS_NOTIFY style, then handling the STN_CLICKED notification in the WM_COMMAND message. (SS_NOTIFY causes WM_COMMAND to trigger in the parent when it is clicked.) This does not trigger when using the "?" button. Thanks!
i am using OnLButtonUp and OnLButtonDblClk in my application but whenever i double click OnLButtonDblClk and OnLButtonUp both called but i wanted only OnLButtonDblClk to be called not OnLButtonUp . How to do this?
The problem is that whenever the user double clicks there are four messages sent:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_LBUTTONUP
This only happens if the user clicks the second time within the "double click time" (use ::GetDoubleClickTime() to get it).
So what you can do is set a timer (with a timeout value equal to the double click time) when the user first clicks and if the second click comes before the timer goes off, you have a double click and you can disregard the button up message.
If the timer goes off, you call your button-up handler.
This technique has the drawback that it delays a bit the response to "Button Up" or single click, depending how you do it, but there's no easy way to discard just the Button Up messages when there's a double click.
EDIT:
If you just want to discard the second WM_LBUTTONUP, you can use a flag. You set it when you receive WM_LBUTTONDBLCLK. Then in the handler for WM_LBUTTONUP you do nothing if it's set (and then you clear it, of course).
OnLButtonUp(UINT nFlags, CPoint point)
{
Sleep(::GetDoubleClickTime());
MSG msg;
if( ::PeekMessage(&msg, NULL, WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK, PM_NOREMOVE) )
return; // LEFT CONTROL TO DBL CLICK ;-)
// NORMAL OnLButtonUp
}
I have a QAbstractItemView that needs to react to single and double click events. The actions are different depending on whether it was single clicked or double clicked. The problem that is occurring is that the single click event is received prior to the double click event.
Is there a recommended way/best practice for distinguishing between the two? I don't want to perform the single click action when the user has actually double clicked.
I am using Qt 4.6
It's a good UI design to make sure your single-clicks and double-clicks are conceptually related:
Single-Click: select icon
Double-Click: select icon and open it
Single-Click: select color
Double-Click: select color and open palette editor
Notice how in these examples the single-click action is actually a subset of the double-click. This means you can go ahead and do your single-click action normally and just do the additional action if the double-click comes in.
If your user interface does something like:
Single-Click: select icon
Double-Click: close window
Then you are setting your users up to fail. Even if they remember what single-clicking does versus double-clicking all the time, it's very easy to accidentally move your mouse too far while double-clicking or wait too long.
Edit:
I'm sorry to hear that.
In that case, I found these two articles useful:
Logical consequences of the way
Windows converts single-clicks into
double-clicks
Implementing
higher-order clicks
You can find answer in the thread titled Double Click Capturing on QtCentre forum;
You could have a timer. Start the
timer in the releaseEvent handler and
make sure the timeout is long enough
to handle the double click first.
Then, in the double click event
handler you can stop the timer and
prevent it from firing. If a double
click handler is not triggered, the
timer will timeout and call a slot of
your choice, where you can handle the
single click. This is of course a
nasty hack, but has a chance to work.
wysota
Using PySide which is the Python binding of Qt 4.8 I saw that single clicks deliver a QEvent.MouseButtonPress event and double clicks deliver a single QEvent.MouseButtonPress event closely followed by a QEvent.MouseButtonDblClick. The delay is approximately about 100ms on Windows. That means you still have a problem if you need to differentiate between single and double clicks.
The solution needs another QTimer with a slightly higher delay than the inbuilt delay (adding some overhead). If you observe a QEvent.MouseButtonPress event you start your own timer, in case of timeout it is a single click. In case of a QEvent.MouseButtonDblClick it is a double click and you stop the timer to avoid counting as single click.
I have a hook setup for getting mouse events in a plugin I develop. I need to get the WM_LBUTTONDBLCLK, and I expect the message flow to be:
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK
If I call the next hook when dealing with the first WM_LBUTTONDOWN, then the flow is as expected. However, if I return my own result, then the expected double click comes as a mouse down message. Any idea why this is happening? I need the message to stop after I handle it, and not have it passed to the next hook.
After having done a little reading over at the MSDN, I think the explanation of this behaviour lies in this remark on the WM_LBUTTONDBLCLK page:
Only windows that have the CS_DBLCLKS
style can receive WM_LBUTTONDBLCLK
messages, which the system generates
whenever the user presses, releases,
and again presses the left mouse
button within the system's
double-click time limit.
If your program is returning a nonzero value when it handles WM_LBUTTONDOWN or WM_LBUTTONUP, then those messages aren't sent to the target window -- as expected. However, my inference, based on the above quote, is that since no window with the CS_DBLCLKS style is therefore receiving the messages (since the hook prevents any window from receiving the messages), the system therefore doesn't feel like it needs to generate a WM_LBUTTONDBLCLK.
To put it another way, the system only generates a WM_LBUTTONDBLCLK if and only if (a) a window receives the previous WM_LBUTTONDOWN/WM_LBUTTONUP messages and (b) that window has the CS_DBLCLKS style. Since your hook prevents condition (a) from being satisfied, WM_LBUTTONDBLCLK is never generated and so a WM_LBUTTONDOWN message is sent instead.
As to a workaround, I doubt there's a perfect solution. I assume the reason why you want to receive the WM_LBUTTONDBLCLK message is so your hook knows whether or not a regular WM_LBUTTONDOWN message represents the second click of a double-click, right? In that case, what you could do is read the double-click time from the registry as Faisal suggests and have your hook measure the time between WM_LBUTTONDOWN messages, however there's a large chance that you will get inaccurate results (due to the lag time between the messages being sent). Alternatively if there's some way you could instead redirect the WM_LBUTTONDOWN/WM_LBUTTONUP messages to maybe a hidden window that your hook owns (which has the CS_DBLCLKS style), the system may end up generating a WM_LBUTTONDBLCLK message and sending it to your hidden window, which you can then process in that window's WndProc (though I don't have a lot of experience with hooking so I don't know if this is possible).
Are you calling CallNextHookEx() before returning your own result - according to MSDN's documentation MouseProc it is highly recommended that you call it since when you return your own result you prevent other hooks from being called.
Have you considered using a low level mouse hook? It doesn't require your DLL to be injected into the process being hooked and I find it to be a more consistent and powerful hook (albeit more resource intensive if not coded appropriately) - especially when listening for clicks in some legacy applications (there was one that was coded in ancient delphi) and clicks in applications served via terminal servers (citrix).
The only issue with low level mouse hooks is that they don't receive double clicks per se - which means you have to query the registry for the 'DoubleClickSpeed' and then check for two mouse down events within that interval before triggering a double click.