WM_LBUTTONDOWN + WM_LBUTTONUP combination making drag view - mfc

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.

Related

WinAPI mouse click does not work properly

I am creating program in C++ (Windows 7 ), that controls one specific window by reading its screen and sending back mouse signals (only left-clicks). I am using WinAPI obviously. Problem is with the mouse signals. My target is to send mouse events independently on actual cursor position. (i.e. it can run on "the background" and the window does not have to be visible).
I tried the obvious solution using SendMessage (or PostMessage):
PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
this_thread::sleep_for (std::chrono::milliseconds(100));
PostMessage(hwnd, WM_LBUTTONUP , MK_LBUTTON, MAKELPARAM(x, y));
I think the commands work fine but there is some problem with how the application process the click events. It seems it does not take into account the parameters x,y and instead when WM_LBUTTONUP is called, it asks OS where the cursor is and make the click on that location. So in the end the click occurs always on the location of cursor (if it is inside the window).
I also tried to send WM_MOUSEMOVE event before WM_LBUTTONUP but it didn't help.
This behavior is really strange, and I fully blame the application not WinAPI. Any ideas how to solve this? Can I maybe somehow trick the window so it thinks that cursor is elsewhere?
If this is the only thing you need then use SendInput with the MOUSEINPUT structure.
If you want to understand why then read on. What you are doing does not work because mouse messages are special. They are not regular messages that arrive and wait for you in the message queue. They are synthesized on demand when you call GetMessage and therefore they get their data from a secret, hidden place . In fact, generally speaking input messages are treated differently than posted messages. Here is some reading material.

What did I miss about WM_MOUSEMOVE?

What I am going to do is very simple, I want to hide the mouse cursor after 1 second if the move does not move or click.
I searched and saw someone recommends using WM_MOUSEMOVE. In my app, however, WM_MOUSEMOVE is simply a dectection of whether the mouse is in the client area. If it is, the app receives WM_MOUSEMOVE continually. I've read the MSDN page but I am still confused.
Use WM_SETCURSOR.
Use WM_SETCURSOR for cursor related works. This message is made for that purpose. Your mentioning of client area suggest you probably need to use SetCapture API also.
Another way (or more modern way of doing) is using TrackMouseEvent. It provides WM_MOUSEHOVER.
The recommendation is correct. What you need to do is define a timer (for example, one that triggers the WM_TIMER message).
You activate it in the first mouse movement (WM_MOUSEMOVE). If a mouse movement won't occur within the interval you defined for the timer, the WM_TIMER event will fire and you can then hide the mouse.
Each time the WM_MOUSEMOVE event fires, you simply restart the timer (using its dedicated API). So that WM_MOUSEMONVE events prevent the timer from expiring. If WM_MOUSEMOVE stop arriving (because you don't move the mouse anymore), the timer will tick without interrupts until it elapses and fires.

How to use mouse hook so current window never sees specific mouse message?

I want some window to never receive mouse wheel up/downs, i can control this messages trough my mouse hook fine but is there a way to make a window never receive those messages?
I can validate the window trough mouse hook and check if its active then just never send that message to it.
I installed mouse hook globally so i believe i have everything needed.
AFAIK hooks may not block the message from reaching the wndproc of the appropriate window.
You may however achieve what you need by subclassing the appropriate windows. That is, replace the window procedure of the appropriate window (use SetWindowLongPtr with GWL_WNDPROC flag) by your wndproc. It should pass all the messages to the original wndproc, apart from those that you want to filter-out.

Recognizing unknown mouse buttons

So I've been writing a simple Windows program, and it really irks me how in some other programs, they can't recognize the full range of input. For example, in Starcraft 2, you can't bind the extra two mouse buttons on a five-button mouse. For keyboard input, I've been using the WPARAM of the WM_KEYDOWN message, so that if it's unrecognized, I can still recognize it later, even if not display it in a usable form. But for mouse buttons, I've come a cropper, because they have their own messages. So if in the future, I get a seven-button mouse, how can I recognize the sixth and seventh buttons without having to re-write my application?
I don't think there is a generic "WM_BUTTONDOWN" message available.
The best way to check that out is to use Spy++ on a window. You'll see that there is no generic message sent out. Plus the actual values of all the WM_xxBUTTONDOWN do not follow any pattern either.
What I would do is configure the app to be able to understand 6 new messages entered manually or configured somewhere, for WM_[Z]BUTTONDOWN, WM_[Z]BUTTONUP and WM_[Z]BUTTONDBLCLK, plus all the corresponding WM_NCxxx messages, because luckily (sort of...), all existing messages more or less share the same wParam + lParam pattern.

MouseProc hook and WM_LBUTTONDBLCLK

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.