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.
Related
I`m making a c++ application with the KINECT. I basically want to use it to send alt f4 to close the current focused window not my application, as you would normally pressing alt f4 on the keboard. Thanks in advance.
Im already using VkKeyScanA to input a few other keys but i just cant find the key code for alr+f4
There's more than one way to do this. Emulating keystrokes is the last thing you should do, very hard to get right since you cannot control the keyboard state of the process well enough.
First one is GetForegroundWindow + SendMessage to send the WM_SYSCOMMAND, SC_CLOSE command. Which is what Alt+F4 does when it is processed by the default window procedure. Which in turn sends WM_CLOSE by default if the program did not override the WM_SYSCOMMAND processing.
If you create your own window then you should favor avoiding trying to find the foreground window. Send WM_APPCOMMAND with the APPCOMMAND_CLOSE command to your own window. Your call to DefWindowProc() forwards the command through several layers to the shell.
In case you are considering a more forceful way, like WM_CLOSE then do review Raymond Chen's recent blog post.
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'm trying to make a program that would update another window text input with the color value under the mouse. The problem is that I have no idea where I put this check WM_MOUSEMOVE, since I haven't created the desktop window myself.
I tried to create own DialogBox which shows the values, but the WM_MOUSEMOVE only works within that DialogBox, not outside of it.
I'm not expert with this, but from what I've read, you need to listen for WM_INPUT message.
In order to start receiving that message, your application needs to register for listening to the mouse.
Read this: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645543(v=vs.85).aspx#_win32_Reading_Raw_Input
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.
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.