C# 如何将虚拟键码转换为字符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/318777/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# How to translate virtual keycode to char?
提问by Horas
I am trying to map a virtual keycode to a char.
我正在尝试将虚拟键码映射到字符。
My code uses ProcessCmdKey to listen to WM_KEYDOWN which gives me access to the key pressed. For example, when I press single quote I get a key of 222 which I want to have it mapped to keychar 39 which represents... you guessed it... single quote.
我的代码使用 ProcessCmdKey 来侦听 WM_KEYDOWN,这使我可以访问按下的键。例如,当我按下单引号时,我得到一个 222 的键,我想将它映射到 keychar 39 代表...你猜对了...单引号。
My dev context is: - .net Framework 2.0 - UserControl placed in a lot of places
我的开发环境是: - .net Framework 2.0 - UserControl 放置在很多地方
Do you know the answer to the question?
你知道问题的答案吗?
回答by Horas
Yes, I did use the MapVirtualKey
method. But I was expecting more details on how to use it: what DllImport
directive to use, what enum
is specific for mapping to characters, etc.
是的,我确实使用了该MapVirtualKey
方法。但我期待更多关于如何使用它的细节:使用什么DllImport
指令,什么enum
是特定于映射到字符的,等等。
I don't like these answers where you google for like 5 seconds and then just suggest a solution: the real challenge is to put all the pieces together and not have to waste your time with tons of sample-less MSDN pages or other coding forums in order to get your answer. No offense plinth, but your answer (even good) was worhtless since I had this answer even before posting my question on the forum!
我不喜欢这些答案,你在谷歌上搜索 5 秒钟,然后只是提出一个解决方案:真正的挑战是将所有部分放在一起,而不必在大量无样本的 MSDN 页面或其他编码论坛上浪费时间为了得到你的答案。没有冒犯底座,但是您的回答(甚至是好)毫无价值,因为我什至在论坛上发布我的问题之前就已经有了这个答案!
So there you go, I am going to post what I was looking for - an out-of-the-box C# solution:
所以你去了,我要发布我正在寻找的东西 - 一个开箱即用的 C# 解决方案:
1- Place this directive inside your class:
1- 将此指令放在您的类中:
[DllImport("user32.dll")]
static extern int MapVirtualKey(uint uCode, uint uMapType);
2- Retrieve your char like this:
2- 像这样检索你的字符:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x100;
if (msg.Msg == WM_KEYDOWN)
{
// 2 is used to translate into an unshifted character value
int nonVirtualKey = MapVirtualKey((uint)keyData, 2);
char mappedChar = Convert.ToChar(nonVirtualKey);
}
return base.ProcessCmdKey(ref msg, keyData);
}
Thanks for caring... and enjoy!
感谢您的关心......并享受!
回答by Powerlord
Isn't that what the System.Windows.Form.KeysConverterclass is for?
这不是System.Windows.Form.KeysConverter类的用途吗?
KeysConverter kc = new KeysConverter();
string keyChar = kc.ConvertToString(keyData);
回答by mm.
KeysConverter gets the key name not the keys "text" ex: "Num2" instead of "2" MapVirtualKey will work for english but for non-english chars documentation states using MapVirtualKeyEx but that requires a locale Identifier that identifier is loaded by LoadKeyBoardLayout which requires a culture id constant but then after finding the correct id values it didn't work as i tried it so finally i dumped the whole thing
KeysConverter 获取键名而不是键“文本”,例如:“Num2”而不是“2” MapVirtualKey 适用于英语,但对于使用 MapVirtualKeyEx 的非英语字符文档状态,但这需要一个区域设置标识符,该标识符由 LoadKeyBoardLayout 加载,它需要文化 id 常数,但在找到正确的 id 值后,它在我尝试时不起作用,所以最后我放弃了整个事情
回答by SongWithoutWords
After reading and testing some of the answers provided, I thought I'd suggest an alternative.
在阅读并测试了提供的一些答案后,我想我会建议一个替代方案。
As mentioned by MM, System.Windows.KeysConverter does not provide a character representation of the key but rather the enum's name, e.g. "Enter" instead of '\n'.
正如MM所提到的, System.Windows.KeysConverter 不提供键的字符表示,而是提供枚举的名称,例如“Enter”而不是“\n”。
The MapVirtualKey method suggested by Horas, in answer to his own question, is a good starting point, but still does not support either capslock, or characters entered with the shift key, e.g. '!', '$' and '>'.
Horas在回答他自己的问题时建议的 MapVirtualKey 方法是一个很好的起点,但仍然不支持大写锁定或使用 shift 键输入的字符,例如 '!'、'$' 和 '>'。
An alternative to the MapVirtualKey method, that I am using, is an extension method for the Keys class:
我正在使用的 MapVirtualKey 方法的替代方法是 Keys 类的扩展方法:
public static char ToChar(this Keys key)
{
char c = '
public string KeyCodeToUnicode(Keys key)
{
byte[] keyboardState = new byte[255];
bool keyboardStateStatus = GetKeyboardState(keyboardState);
if (!keyboardStateStatus)
{
return "";
}
uint virtualKeyCode = (uint)key;
uint scanCode = MapVirtualKey(virtualKeyCode, 0);
IntPtr inputLocaleIdentifier = GetKeyboardLayout(0);
StringBuilder result = new StringBuilder();
ToUnicodeEx(virtualKeyCode, scanCode, keyboardState, result, (int)5, (uint)0, inputLocaleIdentifier);
return result.ToString();
}
[DllImport("user32.dll")]
static extern bool GetKeyboardState(byte[] lpKeyState);
[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll")]
static extern IntPtr GetKeyboardLayout(uint idThread);
[DllImport("user32.dll")]
static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);
';
if((key >= Keys.A) && (key <= Keys.Z))
{
c = (char)((int)'a' + (int)(key - Keys.A));
}
else if((key >= Keys.D0) && (key <= Keys.D9))
{
c = (char)((int)'0' + (int)(key - Keys.D0));
}
return c;
}
The method shown above will provide support for alphanumeric characters. Support for additional characters could be implemented with either a switch statement or lookup table.
上面显示的方法将提供对字母数字字符的支持。可以使用 switch 语句或查找表来实现对附加字符的支持。
回答by Ivan Petrov
I was looking for something similar but I needed the character mapped to the current keyboard layout. Since none of the above answers fulfilled my requirements, here is what I came up with.
我正在寻找类似的东西,但我需要映射到当前键盘布局的字符。由于上述答案均未满足我的要求,因此我想出了以下答案。
public static string GetKeyString(Key key, ModifierKeys modifiers)
{
string result = "";
if (key != Key.None)
{
// Setup modifiers
if (modifiers.HasFlag(ModifierKeys.Control))
result += "Ctrl + ";
if (modifiers.HasFlag(ModifierKeys.Alt))
result += "Alt + ";
if (modifiers.HasFlag(ModifierKeys.Shift))
result += "Shift + ";
// Get string representation
string keyStr = key.ToString();
int keyInt = (int)key;
// Numeric keys are returned without the 'D'
if (key >= Key.D0 && key <= Key.D9)
keyStr = char.ToString((char)(key - Key.D0 + '0'));
// Char keys are returned directly
else if (key >= Key.A && key <= Key.Z)
keyStr = char.ToString((char)(key - Key.A + 'A'));
// If the key is a keypad operation (Add, Multiply, ...) or an 'Oem' key, P/Invoke
else if ((keyInt >= 84 && keyInt <= 89) || keyInt >= 140)
keyStr = KeyCodeToUnicode(key);
result += keyStr;
}
return result;
}
private static string KeyCodeToUnicode(Key key)
{
byte[] keyboardState = new byte[255];
bool keyboardStateStatus = GetKeyboardState(keyboardState);
if (!keyboardStateStatus)
{
return "";
}
uint virtualKeyCode = (uint)KeyInterop.VirtualKeyFromKey(key);
uint scanCode = MapVirtualKey(virtualKeyCode, 0);
IntPtr inputLocaleIdentifier = GetKeyboardLayout(0);
StringBuilder result = new StringBuilder();
ToUnicodeEx(virtualKeyCode, scanCode, new byte[255], result, (int)5, (uint)0, inputLocaleIdentifier);
return result.ToString();
}
[DllImport("user32.dll")]
static extern bool GetKeyboardState(byte[] lpKeyState);
[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll")]
static extern IntPtr GetKeyboardLayout(uint idThread);
[DllImport("user32.dll")]
static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);
回答by edupeux
I've just written an improvement of Ivan Petrov answerto display a string representation of pressed key combinations in WPF, see my code below:
我刚刚编写了Ivan Petrov 答案的改进,以在 WPF 中显示按键组合的字符串表示,请参阅下面的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TextInput += MainWindow_TextInput;
}
private void MainWindow_TextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
{
txtInput.Text += e.Text;
}
}
回答by Francesco Bonizzi
If you are using WPF (I didn't try it with WinForms), there is a very simple solution that returns directly the pressed char, the TextInput Eventof Window.
如果您使用的是 WPF(我没有用 WinForms 尝试过),有一个非常简单的解决方案可以直接返回按下的字符,即Window的TextInput 事件。
##代码##