在 KeyDown 事件中检测单引号键
Detect single quote key on KeyDown event
我希望 TextBox 通过使用 KeyDown 事件只接受一些特定的字符。我已经让它工作了,除了一个字符,单引号。为了获得将要写入的字符,我使用 (char)e.KeyValue
它适用于除引号之外的所有字符(它给出 Û)。我知道我可以只使用 e.KeyCode
但它的值是 Keys.Oem4
,AFAIK 可能因系统而异。
有什么方法可以持续检测单引号按键吗?
代码片段:
char c = (char)e.KeyValue;
char[] moves = { 'r', 'u', ..., '\'' };
if (!(moves.Contains(c) || e.KeyCode == Keys.Back || e.KeyCode == Keys.Space))
{
e.SuppressKeyPress = true;
}
正如@EdPlunkett 所建议的,this answer 对我有用:
[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);
public static string KeyCodeToUnicode(System.Windows.Forms.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();
}
我已经用了很长时间了。它可以很好地处理单引号。 e.KeyChar == 39 '\'' 和 e.Handled = true 的行为完全符合您的预期。我用 KeyPress 事件测试了它并且也在那里工作。
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
if (e.KeyChar == (char)8) // backspace
return;
if (e.KeyChar == (char)3) // ctrl + c
return;
if (e.KeyChar == (char)22) // ctrl + v
return;
typedkey = true;
if (_allowedCharacters.Count > 0) // if the string of allowed characters is not empty, skip test if empty
{
if (!_allowedCharacters.Contains(e.KeyChar)) // if the new character is not in allowed set,
{
e.Handled = true; // ignoring it
return;
}
}
if (_disallowedCharacters.Count > 0) // if the string of allowed characters is not empty, skip test if empty
{
if (_disallowedCharacters.Contains(e.KeyChar)) // if the new character is in disallowed set,
{
e.Handled = true; // ignoring it
return;
}
}
}
我希望 TextBox 通过使用 KeyDown 事件只接受一些特定的字符。我已经让它工作了,除了一个字符,单引号。为了获得将要写入的字符,我使用 (char)e.KeyValue
它适用于除引号之外的所有字符(它给出 Û)。我知道我可以只使用 e.KeyCode
但它的值是 Keys.Oem4
,AFAIK 可能因系统而异。
有什么方法可以持续检测单引号按键吗?
代码片段:
char c = (char)e.KeyValue;
char[] moves = { 'r', 'u', ..., '\'' };
if (!(moves.Contains(c) || e.KeyCode == Keys.Back || e.KeyCode == Keys.Space))
{
e.SuppressKeyPress = true;
}
正如@EdPlunkett 所建议的,this answer 对我有用:
[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);
public static string KeyCodeToUnicode(System.Windows.Forms.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();
}
我已经用了很长时间了。它可以很好地处理单引号。 e.KeyChar == 39 '\'' 和 e.Handled = true 的行为完全符合您的预期。我用 KeyPress 事件测试了它并且也在那里工作。
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
if (e.KeyChar == (char)8) // backspace
return;
if (e.KeyChar == (char)3) // ctrl + c
return;
if (e.KeyChar == (char)22) // ctrl + v
return;
typedkey = true;
if (_allowedCharacters.Count > 0) // if the string of allowed characters is not empty, skip test if empty
{
if (!_allowedCharacters.Contains(e.KeyChar)) // if the new character is not in allowed set,
{
e.Handled = true; // ignoring it
return;
}
}
if (_disallowedCharacters.Count > 0) // if the string of allowed characters is not empty, skip test if empty
{
if (_disallowedCharacters.Contains(e.KeyChar)) // if the new character is in disallowed set,
{
e.Handled = true; // ignoring it
return;
}
}
}