我正在尝试将虚拟键码映射到char。
我的代码使用ProcessCmdKey来监听WM_KEYDOWN,这使我可以访问按下的键。例如,当我按单引号时,我得到一个222的密钥,我希望它映射到keychar 39,代表...你猜对了......单引号。
我的开发背景是: - .net Framework 2.0 - UserControl放置在很多地方
你知道问题的答案吗?
答案 0 :(得分:41)
这不是System.Windows.Form.KeysConverter类的用途吗?
KeysConverter kc = new KeysConverter();
string keyChar = kc.ConvertToString(keyData);
答案 1 :(得分:21)
是的,我确实使用了MapVirtualKey
方法。但是我期待更多有关如何使用它的细节:使用DllImport
指令,enum
特定于映射到字符等等。
我不喜欢这些答案,你谷歌5秒钟,然后只是建议一个解决方案:真正的挑战是把所有的部分放在一起,而不是浪费你的时间与大量的无样本MSDN页面或其他编码论坛,以获得您的答案。没有冒犯的基础,但是你的回答(甚至是好的)是无法解决的,因为我甚至在论坛上发布我的问题之前就得到了这个答案!
所以,你去,我将发布我想要的东西 - 一个开箱即用的C#解决方案:
1-将此指令放在您的班级中:
[DllImport("user32.dll")]
static extern int MapVirtualKey(uint uCode, uint uMapType);
2-像这样检索你的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);
}
感谢关心...并享受!
答案 2 :(得分:8)
我正在寻找类似的东西,但我需要将字符映射到当前的键盘布局。由于上述答案均未满足我的要求,因此我提出了这一点。
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);
答案 3 :(得分:7)
在阅读并测试了所提供的一些答案之后,我想我会建议一个替代方案。
如MM所述,System.Windows.KeysConverter不提供密钥的字符表示,而是提供枚举的名称,例如: “输入”而不是“\ n”。
Horas建议的MapVirtualKey方法,回答他自己的问题,是一个很好的起点,但仍然不支持大写,或者用shift键输入的字符,例如: '!','$'和'>'。
我正在使用的MapVirtualKey方法的替代方法是Keys类的扩展方法:
public 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;
}
上面显示的方法将支持字母数字字符。可以使用switch语句或查找表来实现对其他字符的支持。
答案 4 :(得分:1)
KeysConverter获取密钥名称而非密钥“text” 例如:“Num2”而不是“2” MapVirtualKey适用于英语,但非英语字符文档状态使用MapVirtualKeyEx但需要语言环境标识符 该标识符由LoadKeyBoardLayout加载,需要文化ID常量 但是在找到正确的id值之后,它没有工作,因为我尝试了所以最后我抛弃了整个事情
答案 5 :(得分:1)
我刚刚编写了Ivan Petrov answer的改进,以在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);
答案 6 :(得分:-1)
如果您使用的是WPF(我没有在WinForms上尝试过),则有一个非常简单的解决方案,可以直接返回按下的字符,即Window的TextInput Event。
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;
}
}