I have a question about scan code and extended
OK .
I create a simple window in c++ and I want to detect WM_KEYUP only ( VK_UP value )
Now I run spy++ and I press up key I detect my message like this
keydown vk_up crepeat1 scancode 48 extended1 altdown0 frepeat1 up0
Now if I send a message to my application I get the following message
SendMessage ( wnd , WM_KEYDOWN , VK_UP ,1);
keydown vk_up crepeat1 scancode 00 extended0 altdown0 frepeat1 up0
You see the different in scan code and other value.
My question is why this different even I send the same message?
2 is there any way to send scan code ( and other value to my application and get the same value )
Not sure why the difference but you can use keybd_event or SendInput function to synthesize keystrokes.
Check the docs for WM_KEYDOWN. The scan code is contained in bits 16 through 23 in the LPARAM argument. You passed 1, the scan code bits are thus all zero.
This is okayish, there are not a lot of apps that actually check the scancode. Using SendMessage() is however not correct, keyboard messages go into the message queue. You should use PostMessage(). The difference is that many message loops look at keystrokes to implement accelerators (aka shortcut keys). And call TranslateMesssage() to turn WM_KEYDOWN messages in WM_CHAR messages for typing keys.
There's another problem, an unsolvable one, you cannot control the state of the keyboard. The Ctrl, Alt and Shift modifiers. If the user happens to have the, say, Shift key pressed, the app will see Shift+Up, it may well interpret it very differently, editors certainly do. Only using SendInput() is a cure for that.
SendMessage ( wnd , WM_KEYDOWN , VK_UP ,0x00480001);
Related
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.
I just started using Raw Input for my app.
Getting straight to the question, in the legacy WM_KEYDOWN messages, the lParam could be checked to obtain extra information about the key press. Like these-
Bits Meaning
0-15 The repeat count for the current message.
The value is the number of times the keystroke is autorepeated as a
result of the user holding down the key. If the keystroke is
held long enough, multiple messages are sent. However, the repeat
count is not cumulative.
16-23 The scan code. The value depends on the OEM.
24 Indicates whether the key is an extended key, such as the right-hand
ALT and CTRL keys that appear on an enhanced 101- or 102-key
keyboard. The value is 1 if it is an extended key; otherwise, it is
0.
25-28 Reserved; do not use.
29 The context code. The value is always 0 for a WM_KEYDOWN message.
30 The previous key state. The value is 1 if the key is down before the
message is sent, or it is zero if the key is up.
31 The transition state. The value is always 0 for a WM_KEYDOWN
message.
I want to know if a WM_INPUT message is for a repeated key, so that I can ignore that message.(turn off keyrepeat.)
The trouble I am having is that this information can't be found for the WM_INPUT message. the lParam of the WM_INPUT message contains the handle to a RAWINPUT structure. On doing some research, I found that inside RAWINPUT::header contains a member called wparam in it and MSDN describes it as
wParam
Type: WPARAM
The value passed in the wParam parameter of the WM_INPUT message.
Will I find the required information in here or is it somewhere else?
The RAW Input API does not provide repeat counts. It is raw data coming from the keyboard directly. The repeat count is calculated at a higher level when the WM_KEY... messages are generated. Using WM_INPUT, you will have to manually keep track of the down/up states of each key to determine their repeat counts yourself. When a key goes down, start counting each WM_INPUT message for that key. When the key goes up, stop counting it.
I needed the same information you are looking for, and I found a reasonable work-around. I didn't care about the key repeat count, I just wanted to know if a WM_INPUT message represents an auto-repeat even if the initial key press occurred while my application was not in focus and the key continued to be held when focus switched to my application.
Throwing out all but the first WM_INPUT message is not sufficient to discern this, as keys held prior to gaining focus will look like new key events after gaining focus. You need the information in WM_KEYDOWN/WM_SYSKEYDOWN lparam bit 30, and it's apparently not available from WM_INPUT.
We work around this by requesting to continue receiving legacy input messages when registering for raw input by omitting the RIDEV_NOLEGACY flag. We get both raw and legacy messages, which arrive interleaved. For any relevant WM_INPUT message containing key information, it will be followed by legacy messages relating to that key before any additional WM_INPUT messages arrive. Our Windows input library gathers key info from both raw & legacy messages before evaluating the key event and it works very well for us.
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.
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.
I'm trying to get my application to do something when CTRL+S is pressed. I'm just not sure how the W and L params work for WM_KEYDOWN. MSDN has something about bit fields which i'm not sure about. How can I detect CTRL and S?
Thanks
What do I do if another control aside from hWnd has focus?
Well, this is the big list of virtual key codes.
CTRL-S is going to be sent through as 2 WM_KEYDOWN messages - a message when the ctrl key is pressed (VK_LCONTROL or VK_RCONTROL) followed by a 0x53 for the "S" key.
Rather than processing both messages, wait for the key down message for the 'S' press then call GetKeyState using the magic value VK_CONTROL (otheriwse you'd need to test individually for the left AND right control keys) to see if the S was pressed with CTRL held down.
--
Obviously, keyboard messages are sent directly to the window that has focus. To get accelerator combinations to work at the application scope you need to check the messages before dispatching them to the focus window - i.e. in your message pump. See the documentation for TranslateAccelerator.
If you want to handle system wide keypresses, the other answer points to the hot key api.
When the WPARAM is equal to the CTRL VKcode, then set a bool in the state of your object. Then, when S comes up, if Ctrlbool, you've got CTRL-S.