我正在尝试将虚拟键码映射到字符。
我的代码使用ProcessCmdKey监听WM_KEYDOWN事件,这使我可以访问按下的键。例如,当我按单引号键时,我得到一个222的键码,我希望将其映射到代表单引号的键字符39。
我的开发环境是:
- .net Framework 2.0
- 在很多地方放置的用户控件
你知道答案吗?
这不就是 System.Windows.Form.KeysConverter 类的作用吗?
KeysConverter kc = new KeysConverter();
string keyChar = kc.ConvertToString(keyData);
(new KeysConverter()).ConvertToString(Keys.OemQuestion)
(剧透:它会返回OemQuestion
而不是?
)。此外,如何处理Shift键也不清楚。有有效的解决方案吗? - Hi-AngelKeys.Shift | Keys.D
。 - Powerlord是的,我确实使用了MapVirtualKey
方法。但我期望能得到更多使用该方法的细节:应该使用什么DllImport
指令,哪些enum
具体用于映射字符等。
我不喜欢那些只是在谷歌上搜索几秒钟然后建议解决方案的答案:真正的挑战在于把所有的东西放在一起,而不必浪费时间去查找没有示例的MSDN页面或其他编码论坛以获得答案。没有冒犯plinth的意思,但你的答案(即使很好)也是无用的,因为在发布我的问题之前我已经有了这个答案!
所以,在这里,我要发表我正在寻找的——一个开箱即用的C#解决方案:
1- 将此指令放入您的类内:
[DllImport("user32.dll")]
static extern int MapVirtualKey(uint uCode, uint uMapType);
按照以下方式检索您的char:
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);
}
感谢关注……请享受!
我正在寻找相似的东西,但是我需要将字符映射到当前键盘布局。由于上面的答案都没有满足我的要求,所以我想出了以下解决方案。
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);
byte[] keyboardState = new byte[255];
还是来自 pinvoke.net 的 byte[] bKeyState = new byte[256];
? - gridtrakpublic static char ToChar(this Keys key)
{
char c = '\0';
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;
}
System.Windows.Forms
还是 System.Windows.Input
?Key
是 System.Windows.Input
中的一个枚举,但在这里没有被使用,而且不清楚 Keys
是从哪里来的。 - user1618054我刚刚改进了Ivan Petrov的回答,以在WPF中显示按键组合的字符串表示形式,请参见下面的代码:
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);
space
或 TAB
键,结果将是不可见的,使用户认为没有返回结果。是否有一个非字母数字键代码及其相应名称的列表,以便我们可以返回所按键的名称? - pookieGetKeyString
方法中加入更多的条件。 - edupeuxKeysConverter 可以获取键名而不是键的“文本” 例如:“Num2”而不是“2” MapVirtualKey 对于英语可以工作,但对于非英语字符,文档指出使用 MapVirtualKeyEx,但这需要区域标识符 该标识符由 LoadKeyBoardLayout 加载,它需要一个文化 ID 常量 但是在找到正确的 ID 值之后,它没有起作用,所以最终我放弃了整个事情
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;
}
}