Translating Windows.forms.Keys to real local keyboard value - c#

I use the namespace Windows.Forms.Keys
I would like to be able to catch and use some special like characters like é,è,à,ç, but when the program fire the event KeyDown, the KeyEventArg just return me the value "D1" to "D9".
What could I do to get the real char associated to these keys ?

Short answer: use KeyPress instead of KeyDown.
KeyDown is really designed to work with the physical layout of the keyboard (well, the logical layout of the physica... forget it :D). This is very different from the character that given physical key represents.
On the other hand KeyPress is all about characters being input from the keyboard, rather than keys being pressed, really. Note how KeyPress supports features like AltGr + someKey and char repetition etc.
If you really need to use KeyDown/KeyUp, you'll have to emulate the way windows keyboard system works to determine the char to output (for example, if you're making a keyboard mapping screen for a game or something like that). You can use the ToAscii WinAPI method (https://msdn.microsoft.com/en-us/library/ms646316.aspx).
Apart from that, you still have to understand the meaning of the key combinations - for example, on my keyboard, if I press 1, I get +. If I press Shift+1, I get 1. If I press AltGr + 1, I get !. Which of those do you care about? Maybe Shift + 1 should be interpreted as 1 (what KeyPress does). Maybe it should be interpreted as Shift + 1 (the easiest, you already have that). And maybe it should be interpreted as Shift + +, the way it's usually used for hotkey bindings or keyboard mappings in games.
It should be pretty obvious by now that this is actually far from trivial. You need some mechanism to interpret the "raw" input data - and different interpretations make different sense for different initial conditions. You're basically asking for a mixed approach between the two obvious options - you're mixing virtual keys and "real" characters.

Related

vb.net or c#.net console.readkey shift+number chars

I've been having some trouble getting the correct code for incoming keystrokes on the console for shift+number characters. For example, using:
cki = Console.ReadKey(True)
Console.WriteLine("You pressed the '{0}' key.", cki.Key)
If I press shift+2, I'm hoping to get the ascii 64 (for the '#' character), but instead I get 50 (for the '2' character).
Now, I know you can get the modifiers for the key pressed, but that would mean I'd have to program all the special cases for keys like that, and that doesn't seem right.
I need this function, or something like unto it, because of its ability to read keys as they are pressed, without the need to press enter, otherwise I'd just use console.read. Surely I've missed something. Could anyone tell me what it is I've missed?
You're looking for the KeyChar property, which returns the actual character rather than the physical key pressed.
You may want to cast it to int.
It is pretty important to distinguish between keys and characters. The key is the same anywhere in the world, the one on the top row at the left. You can rely on that key always producing ConsoleKey.D2
The character is however very different, it greatly depends on the active keyboard layout. A Northern American user presses Shift+2. A French user presses AltGr+0. A German user presses AltGr+Q. A Spanish user presses AltGr+2. Etcetera.
If you care only about the key then use ConsoleKeyInfo.Key, you do so for all non-typing keys like the function keys for example. Perhaps the typical gaming WASD keys. If you care only about the character, like #, then use ConsoleKeyInfo.KeyChar.

Odd enum values in Windows.Forms.MouseButtons

I found this gem (IMO) in System.Windows.Forms namespace. I'm struggling to figure out why is it set like this.
[Flags]
public enum MouseButtons
{
None = 0,
Left = 1048576,
Right = 2097152,
Middle = 4194304,
XButton1 = 8388608,
XButton2 = 16777216,
}
Can somebody explain why it uses these values (power of 2^20 to 2^24) instead of this:
public enum MouseButtons
{
None = 0,
Left = 1, // 2^0
Right = 2, // 2^1
Middle = 4, // 2^2
XButton1 = 8, // 2^3
XButton2 = 16, // 2^4
}
The first value is 100000000000000000000 in binary, which leaves space for another 20 bits! Why do we need such space and why is it preserved like this?
Enum values used in Winforms do tend to match corresponding bits in the winapi but that's not the case at all for mouse buttons. Explaining this one requires a pretty wild guess.
I do have one, the way you retrieve the state of the mouse buttons without relying on a Windows message is very strange. You call GetAsyncKeyState(), passing VK_LBUTTON through VK_XBUTTON2. Fake virtual keys that actually represent mouse keys and not keyboard keys. This happened way too long ago for me to guess why they did it this way instead of providing a proper GetMouseButtonState() winapi function.
The Keys enumeration has those values as well, like Keys.LButton etcetera. Something else that's special about Keys is that it can also encode the state of a modifier key. There are for example Keys.Control and Keys.ControlKey. And Keys.Shift vs Keys.ShiftKey, etcetera. The first one indicates the state of the key, the second one indicates the actual key. Which permits friendly code like keydata == (Keys.Control | Keys.F) to check if Ctrl+F was pressed.
The significance of these MouseButtons enum values is then that they fit in a Keys enum value to indicate the state of the mouse buttons. Leaving 20 bits available for the bits that encode the key.
Sounds good, doesn't it? The only hiccup is that it is never combined that way within the Winforms object model. But could be in your own code to define a shortcut that also uses the mouse state.
My guess is that it has to do with how the underlying Windows API is passing mouse information to .NET.
Windows packages up which mouse buttons are clicked as well as pointer position in a block of information (think of the old MOUSE_EVENT structure). The enums in .NET are setup the way they are to be efficient, so they probably line up nicely with how the underlying Windows message.
So, instead of getting the lower-level message and having to convert it into a new set of values, .NET just targets the bits in the lower-level message that it is interested in - no conversion, no math, just efficiency.

Sending Windows key using SendKeys

I am working on shortcuts in C#. I succeed implementing Ctrl, Alt and Shift with SendKeys.
Like this;
Ctrl + C:
System.Windows.Forms.SendKeys.SendWait("^c");
or Alt + F4:
System.Windows.Forms.SendKeys.SendWait("%{F4}");
But I can't send "Windows Key" with SendKeys. I tried ex: Win + E : .SendWait("#e") but it's not working. What should I use instead of "#"?
Thanks.
OK turns out what you really want is this: http://inputsimulator.codeplex.com/
Which has done all the hard work of exposing the Win32 SendInput methods to C#. This allows you to directly send the windows key. This is tested and works:
InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.LWIN, VirtualKeyCode.VK_E);
Note however that in some cases you want to specifically send the key to the application (such as ALT+F4), in which case use the Form library method. In others, you want to send it to the OS in general, use the above.
Old
Keeping this here for reference, it will not work in all operating systems, and will not always behave how you want. Note that you're trying to send these key strokes to the app, and the OS usually intercepts them early. In the case of Windows 7 and Vista, too early (before the E is sent).
SendWait("^({ESC}E)") or Send("^({ESC}E)")
Note from here: http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx
To specify that any combination of SHIFT, CTRL, and ALT should be held
down while several other keys are pressed, enclose the code for those
keys in parentheses. For example, to specify to hold down SHIFT while
E and C are pressed, use "+(EC)". To specify to hold down SHIFT while
E is pressed, followed by C without SHIFT, use "+EC".
Note that since you want ESC and (say) E pressed at the same time, you need to enclose them in brackets.
download InputSimulator from nuget package.
then write this:
var simu = new InputSimulator();
simu.Keyboard.ModifiedKeyStroke(VirtualKeyCode.LWIN, VirtualKeyCode.VK_E);
in my case to create new vertial desktop, 3 keys needed and code like this(windows key + ctrl + D):
simu.Keyboard.ModifiedKeyStroke(new[] { VirtualKeyCode.LWIN, VirtualKeyCode.CONTROL }, VirtualKeyCode.VK_D);
Alt+F4 is working only in brackets
SendKeys.SendWait("(%{F4})");
SetForegroundWindow( /* window to gain focus */ );
SendKeys.SendWait("^{ESC}"); // ^{ESC} is code for ctrl + esc which mimics the windows key.
For sending combination of Ctrl+Alt+Right ==> use this ==> "(^%({RIGHT}))"

ConsoleKeyInfo, the Question Mark and Portability

I have a little C# console application that reads a key and checks to see if the key was a question mark:
ConsoleKeyInfo ki = System.Console.ReadKey();
if (ki.ConsoleKey.Oem2) // Do something
I arrived at Oem2 by seeing what value is actually assigned in the debugger, because there is no ConsoleKey code for question mark.
Now I could certainly use ki.KeyChar instead, but the application also needs to respond to certain keys (e.g. media keys) that do not map to characters. It feels inelegant to check both ConsoleKey and KeyChar to determine which key has in fact been pressed. On the other hand, it does not feel safe to rely on Oem2 to always map to ? in all circumstances and regions.
Is it best practice to check both properties to determine which key was in fact pressed?
Any insight into why ConsoleKeyInfo was designed this way is appreciated.
In this case, you will have to check KeyChar == '?'. From MSDN:
Oem2: The OEM 2 key (OEM specific).
So you're just getting lucky in that it happens to be a ? on your equipment.
The ConsoleKeyInfo structure provides KeyChar (a Char value) as well as Modifiers (an enumeration) to help you decide what keys the user had pressed.
I think you should consider what happens when someone has different keyboard layout.
If you want to check for “the key with question mark on my computer”, then use ConsoleKey. But that's probably not a good idea and you should probably adhere to the user's settings and use KeyChar.
But for keys that don't map to to characters (and the user can't remap them by using different keyboard layout), you have to use ConsoleKey.
So, yes, I think you should check both properties in this case.
I guess the reason for this design is that Console.ReadKey() relies on a native function (ReadConsoleInput) that returns an array of KEY_EVENT_RECORD structures in case of a keypress, where each key event has an ASCII/Unicode character representation and a virtual key code. Notice the VK_OEM_2 in my previous link - this is where the ConsoleKey.Oem2 value comes from.

How do I convert a Char into a Keycode in .Net?

I want to convert a string into a series of Keycodes, so that I can then send them via PostMessage to a control. I need to simulate actual keyboard input, and I'm wondering if a massive switch statement is the only way to convert a character into the correct keycode, or if there's a simpler method.
====
Got my solution - http://msdn.microsoft.com/en-us/library/ms646329(VS.85).aspx
VkKeyScan will return the correct keycode for any character.
(And yes, I wouldn't do this in general, but when doing automated testing, and making sure that keyboard presses are responded to correctly, it works reliably enough).
Raymond says this is a bad idea.
http://blogs.msdn.com/oldnewthing/archive/2005/05/30/423202.aspx
For A-z 1-9 you could try build the char into a keycode string string.Format("KEY_KEY_{0}", char.ToString()) then use Enum.Parse to extract the Enum value, but it's a bit of a cludge
Or look at How to convert uint keycode to Keys enum on expert sexchange, and just work around the tricky cases.
I agree a switch statement is kinda awful
Got my solution - http://msdn.microsoft.com/en-us/library/ms646329(VS.85).aspx
VkKeyScan will return the correct keycode for any character.
(And yes, I wouldn't do this in general, but when doing automated testing, and making sure that keyboard presses are responded to correctly, it works reliably enough).
A much more reliable wait to send a string of keystrokes to a window is to use the SendKeys class
System.Windows.Forms.SendKeys("This is a test");
System.Windows.Forms.SendKeys("This is sends CTRL+J ^j");
This will be more predictable and should save you some time.

Categories