I want to create an accelerator for CTRL+A. I noticed that it doesn't work when you leave out FVIRTKEY, i.e. the following code snippet doesn't work:
a.fVirt = FCONTROL;
a.key = 'A';
a.cmd = IDM_ADD;
(just for completeness' sake: using 'a' instead of 'A' doesn't work either)
This, however, works fine:
a.fVirt = FCONTROL|FVIRTKEY;
a.key = 'A';
a.cmd = IDM_ADD;
Can somebody explain this behaviour? MSDN says that if FVIRTKEY isn't set, "key" is interpreted as a character code which I presume to be ASCII. But it doesn't work which leaves me somewhat puzzled.
Thanks!
The system translates certain Ctrl key combinations into ASCII control codes. The combination Ctrl+A is translated to the ASCII ctrl-A (SOH) character (ASCII value 0x01). This is the reason why your first snippet does not expose the desired behavior: It requires input that is impossible to enter. This is documented under Keyboard Input in the MSDN.
Also note that not providing the FVIRTKEY flag makes the specified key case-sensitive, i.e. 'a' and 'A' map to different input. It is usually desirable to use virtual key codes, to provide a consistent keyboard UI. The implications are explained under About Keyboard Accelerators - Accelerator Keystroke Assignments.
Related
I'm trying to check if the colon key is pressed, I'm using a English keyboard which means colon is shift + ;, my though was to read the keyboard state and then check the status of the scancode:
SDL_PumpEvents();
const uint8 *keyState = SDL_GetKeyboardState(NULL);
printf("keystate %d\n", keyState[scancode]);
but then I realized there is a scancode for the keypad colon SDL_SCANCODE_KP_COLON equivalent toSDLK_KP_COLON, but there is no scancode for SDLK_COLON (In case you are wondering: I tried with the keypad version and is not working).
So, I wonder why there is no equivalent scancode for SDLK_COLON and what's the best way to do this instead?
There is no colon scancode because there is no key on an ANSI (US) layout keyboard that produces a colon without modifiers. SDLK_COLON exists because there are layouts where a key produces a colon without modifier, like the French layout where the key corresponding to SDL_SCANCODE_PERIOD (dot . or greater-than sign >) makes a colon : or a slash / (with shift). So if you press that key on a French keyboard, you receive an event with SDL_SCANCODE_PERIOD and SDLK_COLON.
What I assume you want is to know if the user typed a colon, which has nothing to do with scancodes or even keycodes when dealing with different keyboard layouts. For that, you need a SDL_TextInputEvent. Check out the wiki's tutorial about it.
Or you could use SDL_SCANCODE_SEMICOLON, check what that key corresponds to for the user, and display that so the user knows what key to press (it would be the รน key for a French keyboard).
I am trying to attach Commands to buttons. This method works for 'q' and 'm', but it is not working for 'p' character.
Using '-112' did not solve the problem either. using minus symbol works for arrow keys but not for 'p'.
addKeyListener(113, new CommandA(gameWorld)); // q
addKeyListener(109, new CommandB(gameWorld)); // m
addKeyListener(112, new CommandC(gameWorld)); // p - Not Working
pressing 'p' does nothing.
UPDATE
Found a workaround...
This won't work for you on the device anyway as most devices are touch devices. The virtual keyboards on such devices don't send these events anyway. The arrow keys send undocumented values which differ a lot and you should "theoretically" use the game key API and not the key API. But again this won't work on the devices most commonly used today.
The characters aren't just numbers. They are literally the character value (int)'p'. There is no special treatment for them but it's possible that something in the system is grabbing that specific character as it's commonly associated with a print shortcut.
On different machines, in an OnKeyDown override, the e.Key values are not necessarily consistent. For instance, on my Mac running Win7-64 under Boot Camp, the backslash key is reported as Key.OemQuote and not Key.OemBackslash as one would expect, which makes no sense considering that's not even on the same key. On a co-worker's Dell, it's reported as something else entirely.
However, in both cases, the correct backslash character is appearing in a textbox when typing so the OS obviously somehow knows that's what character that key is tied to.
We're trying to determine if, given a keycode on a particular system, you can get the corresponding character, if any, which that key represents (assuming no modifiers are pressed.)
Note: I am already aware of the OnPreviewTextInput and OnTextInput events which deal with the characters that are typed, but that is not what I am asking.
I am specifically asking about a function that takes a KeyCode as a parameter and returns what character would be displayed on-screen if that key were to be pressed.
For instance, on my machine, the function would take Key.OemQuote and would return the backslash character. Passing in Key.Control would return null (since nothing actually appears when Control is pressed alone.)
Note: I've put up another question about dealing with the different key codes specifically that may look similar to this question, but this is a very specific separate question relating to a function that takes such a code and returns a character, so please do not mark this as a duplicate. It is not.
I think the answer in this thread applies.
Also check out MapVirtualKey
PInvoke
I'm trying to make a simple text editor with winapi, its working for simple letter, but its not with capital letter or shift key.
char keys[256];
int x = 0;
while (1)
{
for (x = 0; x <= 256; x++)
{
if (GetAsyncKeyState(x) == -32767)
{
char c[5];
GetKeyboardState(keys);
ToAscii(x, MapVirtualKey(x, 0), keys, c, 0);
putchar(c[0]);
}
}
}
The behaviors of keyboard input are far more complex than what you think. Your method doesn't work because:
GetAsyncKeyState can miss keys. What happens when the user hits a key between calls?
What happens when you hold down a key? What about keyboard repeat?
Most critically, your code assumes a 1:1 relationship between key and character. You don't have any mechanism to deal with combinations like shift / caps lock state, or dead keys.
It would be better if you tried to explain what you're trying to do, and you can get advice on the right way to approach it. Trying to re-invent the behaviors of such a fundamental input device is not likely to be the best approach.
GetAsyncKeyState is likely not the way to go here: the real way to make a text editor type control is to instead handle the WM_KEYDOWN and WM_CHAR messages. Windows will send these to your WndProc when your HWND has focus. This is the technique used by the Windows EDIT and RichEdit controls.
Use WM_KEYDOWN to handle the non-character keys - like arrows (VK_LEFT, VK_RIGHT), page up and so on; and use WM_CHAR for text characters. WM_KEYDOWN tells you the key pressed using a VK_ value, and doesn't take shift state into account; while WM_CHAR does take shift state, so gives you 'A' vs 'a' or '1' vs '!' as appropriate. (Note that you have to have TranslateMessage in your messsage loop for this to happen.)
Having said all that, an even easier/better thing to do is just use the existing Windows EDIT or RichEdit controls and let them do the work for you - there's rarely a good reason to reinvent the wheel - unless you're playing around for fun and learning Win32 perhaps. Writing a proper text editor is pretty complex; there's a lot of non-obvious stuff to consider, especially when you get into non-English text: you'd need to ensure it works correctly with right-to-left text (Arabic, Hebrew), works with IMEs which are used to enter Japanese and Chinese characters. And you have to ensure that your control is accessible to screenreaders so that users with visual impairments can still use the control. EDIT and RichEdit do all this for you.
The actual Notepad app, for example, is just a wrapper for an EDIT control; while WordPad just wraps a RichEdit control; both let the control do all the hard work, and just add the extra UI and file save/load functionality on top.
Try to call
GetKeyState(VK_CAPITAL);
before
GetKeyboardState(keys);
I have a small WIN32 C-Application in which i work with the KBDLLHOOKSTRUCT structure. This structure contains the VK-Code for a pressed key.
I try to convert this to an ASCII-Character. For this i use the Function MapVirtualKey, which works well.
The only problem is, that one VK-Code can stay for multiple chars.
Example:
On my keyboard (Swiss-German) exists the key-char .. If i press Shift+. then it creates a :. The VK-Code is the same. Thats no problem, and i can also check if Shift is pressed or Caps Lock is activated.
My only problem is: How can i get the char ':'?
I need a function like this:
GetKeyChar(vkCode, shift)
I need this to get the "normal" and the "shifted" value of the keyboard. Of course i could hardcode this, but i don't like to do it on this way.
The problem is that the KBDLLHOOKSTRUCT doesn't have all the information you need in order to do the translation. You get a message every time a key is pressed. So for Shift+X, you'll get an input message saying that the Shift key was pressed, and another message saying that the "X" key was pressed.
You need to call GetKeyboardState in order to get the state of the Shift, Alt, Ctrl, (and perhaps other) keys. Then call ToAsciiEx or ToUnicodeEx.
You're looking for ToUnicode, which returns the unicode character generated by that keypress.
The functions you are looking for are: ToAscii, ToAsciiEx, ToUnicode, ToUnicodeEx.
short VkKeyScan(char ch) API has contained the shift information. It translate char to virtual-key code and shift state.
See this: Convert character to the corresponding virtual-key code