How to convert a character in to equivalent System.Windows.Input.Key Enum value?
[DllImport("user32.dll")]
static extern short VkKeyScan(char ch);
static public Key ResolveKey(char charToResolve)
{
return KeyInterop.KeyFromVirtualKey(VkKeyScan(charToResolve));
}
Convert a System.Windows.Input.KeyEventArgs key to a char
See How to convert a character in to equivalent System.Windows.Input.Key Enum value?
Use KeyInterop.VirtualKeyFromKey
instead.
How can I convert 'System.Windows.Input.Key' to 'System.Windows.Forms.Keys'?
Keys formsKey = ...;
Key wpfKey = ...;
wpfKey = KeyInterop.KeyFromVirtualKey((int)formsKey);
formsKey = (Keys)KeyInterop.VirtualKeyFromKey(wpfKey);
The KeyInterop class is the "key," plus the fact that the Windows Forms Keys
enumeration has the same integer values as the Win 32 virtual key codes.
Convert a string, char type to System.Windows.Forms.Keys
The Keys
codes for the numbers and uppercase letters match the corresponding ASCII codes. Assuming you're dealing with ASCII, you can do:
Keys key = (Keys) (byte) char.ToUpper(c);
How to get pressed char from System.Windows.Input.KeyEventArgs?
See this post... how to capture the '#' character on different locale keyboards in WPF/C#?
it has a utility function called GetCharFromKey(Key key)
which gets locale specific character from the Key of the Keyboard event args.
Very useful.
No entry for the Equals key in the System.Windows.Input.Key enum?
As pointed out by ChrisF, I needed to engage my brain a little. For what it's worth, the value generated when handling the KeyDown
event is Key.OemPlus
.
Update:
One consequence of this is that, if you're doing the same same as me and you're going to use the command in a menu, you'll probably want to use the overloaded constructor for KeyGesture
that takes a 3rd parameter of displayString
. For example:
new KeyGesture(Key.Equals, ModifierKeys.Control, "Ctrl+=")
Otherwise, you'll see the keyboard shortcut displayed as (in my case) "Ctrl+OemPlus", which isn't exactly desirable. Admittedly, the above still isn't great, but it's better than "OemPlus".
Key (enum) to string
Use a Dictionary<TKey, TValue>
:
Class-level:
private readonly Dictionary<string, string> operations = new Dictionary<string, string>;
public ClassName() {
// put in constructor...
operations.Add("Subtract", "-");
// etc.
}
In your method, just use operations[e.Key.ToString()]
instead.
Edit: Actually, for more efficiency:
private readonly Dictionary<System.Windows.Input.Key, char> operations = new Dictionary<System.Windows.Input.Key, char>;
public ClassName() {
// put in constructor...
operations.Add(System.Windows.Input.Key.Subtract, '-');
// etc.
}
In your method, just use operations[e.Key]
instead.
Get KeyCode from a char?
This one might be more easily explained with an example program than anything else:
namespace KeyFinder
{
class Program
{
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
[DllImport("user32.dll")]
static extern bool UnloadKeyboardLayout(IntPtr hkl);
[DllImport("user32.dll")]
static extern IntPtr LoadKeyboardLayout(string pwszKLID, uint Flags);
public class KeyboardPointer : IDisposable
{
private readonly IntPtr pointer;
public KeyboardPointer(int klid)
{
pointer = LoadKeyboardLayout(klid.ToString("X8"), 1);
}
public KeyboardPointer(CultureInfo culture)
:this(culture.KeyboardLayoutId){}
public void Dispose()
{
UnloadKeyboardLayout(pointer);
GC.SuppressFinalize(this);
}
~KeyboardPointer()
{
UnloadKeyboardLayout(pointer);
}
// Converting to System.Windows.Forms.Key here, but
// some other enumerations for similar tasks have the same
// one-to-one mapping to the underlying Windows API values
public bool GetKey(char character, out Keys key)
{
short keyNumber = VkKeyScanEx(character, pointer);
if(keyNumber == -1)
{
key = System.Windows.Forms.Keys.None;
return false;
}
key = (System.Windows.Forms.Keys)(((keyNumber & 0xFF00) << 8) | (keyNumber & 0xFF));
return true;
}
}
private static string DescribeKey(Keys key)
{
StringBuilder desc = new StringBuilder();
if((key & Keys.Shift) != Keys.None)
desc.Append("Shift: ");
if((key & Keys.Control) != Keys.None)
desc.Append("Control: ");
if((key & Keys.Alt) != Keys.None)
desc.Append("Alt: ");
return desc.Append(key & Keys.KeyCode).ToString();
}
public static void Main(string[] args)
{
string testChars = "Aéש";
Keys key;
foreach(var culture in (new string[]{"he-IL", "en-US", "en-IE"}).Select(code => CultureInfo.GetCultureInfo(code)))
{
Console.WriteLine(culture.Name);
using(var keyboard = new KeyboardPointer(culture))
foreach(char test in testChars)
{
Console.Write(test);
Console.Write('\t');
if(keyboard.GetKey(test, out key))
Console.WriteLine(DescribeKey(key));
else
Console.WriteLine("No Key");
}
}
Console.Read();//Stop window closing
}
}
}
Output:
he-IL
A Shift: A
é No Key
ש A
en-US
A Shift: A
é No Key
ש No Key
en-IE
A Shift: A
é Control: Alt: E
ש No Key
(Though your own console might mess up ש and/or é depending on settings and fonts).
Note that the Windows kludge of using Ctrl+Alt as a substitute in case a keyboard has no AltGr key is precisely how it is reported, it's only at a lower level again that the two are treated as separate, which is one of the things that makes Windows keyboards less flexible (Alt + AltGr is meaningless in Windows).
Edit: The constructor for KeyboardPointer
that takes a CultureInfo
has obvious ease of use, but that which takes a number is useful for secondary keyboards for a given culture. E.g. en-US most often uses 0x0149, but there are variants with a different higher word (0x00010149, 0x00020149, 0x00030149, etc.) for variant layouts like Dvorak, extended support for characters (the so-called "International US" needed to write English words like "naïve", "façade" or "résumé"), and so on.
Related Topics
How to Get the Correct Ip from Http_X_Forwarded_For If It Contains Multiple Ip Addresses
What's a Good Way of Doing String Templating in .Net
How to Throttle Requests in a Web API
Dependency Injection - New Instance Required in Several of a Classes Methods
What's the Difference Setting Embed Interop Types True and False in Visual Studio
Azure Shared Access Signature - Signature Did Not Match
Vb.Net Equivalent to C# Var Keyword
C# Keep Session Id Over Httpwebrequest
Can Structs Contain Fields of Reference Types
How to Hide Wpf Datagrid Columns Depending on a Property
What's the Point of a Lambda Expression
How to Open a Serial Port by Friendly Name
Moving Mouse Cursor Programmatically
Changing the Cursor in Wpf Sometimes Works, Sometimes Doesn'T