在一个C#Windows.Forms项目我有一个控件,不提供Keypressed事件(这是一个COM控件 – ESRI地图)。
它仅提供包含KeyEventArgs结构的KeyUp和KeyDown事件。
如何将KeyEventArgs中的信息转换为可显示的Unicode字符,并将当前活动的键盘布局考虑在内?
绕过Windows兼容性链接目录
In-Proc SxS在托pipe代码中打开shell扩展?
如何在C#GUI窗体中运行batch file
如何通过键查找/检查字典值
WCF Windows服务超时
UNIX和Windows开发之间的区别
是否有API调用来开始扫描硬件设备
如何确定给定COM库的线程模型?
.NET CLR不需要操作系统?
WPF richtextBox的冲突语言设置
诀窍是使用一组user32.dll函数: GetwindowThreadProcessId , GetKeyboardLayout , GetKeyboardState和ToUnicodeEx 。
使用控件句柄的GetwindowThreadProcessId函数来实现相关的本地线程ID。
将该线程ID传递给GetKeyboardLayout以获取当前的键盘布局。
调用GetKeyboardState获取当前的键盘状态。 这有助于下一个方法根据修饰符状态决定要生成哪个字符。
最后,用想要的虚拟键代码和扫描代码(这两个可以是相同的),当前的键盘状态,作为字符串保持器的字符串保持器(保持结果),无标志(0)和当前的键盘布局指针。
如果结果不为零,只返回第一个返回的字符。
public class KeyboardHelper { [DllImport("user32.dll",CharSet = CharSet.Unicode,ExactSpelling = true)] private static extern int ToUnicodeEx( uint wVirtKey,uint wScanCode,Keys[] lpKeyState,StringBuilder pwszBuff,int cchBuff,uint wFlags,IntPtr dwhkl); [DllImport("user32.dll",ExactSpelling = true)] internal static extern IntPtr GetKeyboardLayout(uint threadId); [DllImport("user32.dll",ExactSpelling = true)] internal static extern bool GetKeyboardState(Keys[] keyStates); [DllImport("user32.dll",ExactSpelling = true)] internal static extern uint GetwindowThreadProcessId(IntPtr hwindow,out uint processId); public static string CodetoString(int scanCode) { uint procId; uint thread = GetwindowThreadProcessId(Process.GetCurrentProcess().MainWindowHandle,out procId); IntPtr hkl = GetKeyboardLayout(thread); if (hkl == IntPtr.Zero) { Console.WriteLine("Sorry,that keyboard does not seem to be valid."); return string.Empty; } Keys[] keyStates = new Keys[256]; if (!GetKeyboardState(keyStates)) return string.Empty; StringBuilder sb = new StringBuilder(10); int rc = ToUnicodeEx((uint)scanCode,(uint)scanCode,keyStates,sb,sb.Capacity,hkl); return sb.ToString(); } }
Itai Bar-Haim的解决方案很不错,但是却有一个死钥匙的问题。
您第一次用死键的扫描码调用CodetoString(int scanCode)时,ToUnicodeEx()的返回码为-1,您的方法返回正确的值。
但在下一次调用时,ToUnicodeEx()将返回2.结果字符串将在预期的结果之前包含死锁,然后是内存垃圾数据。
例如,我用^(死键)然后用$来调用你的方法。 第一个调用返回^(nice),但第二个调用返回^ $ azertyui。
你必须做两件事来解决这个问题:
1)您必须使用ToUnicodeEx()返回码绝对值来设置您的StringBuilder的长度。 所以你避免在字符后面得到垃圾数据。
2)当ToUnicodeEx()的返回码是-1时,必须把StringBuilder的第一个字符作为你的方法的结果。 然后,您必须从键盘状态中删除死锁:使用空格键的扫描代码调用ToUnicodeEx()。
另一个问题可能是:如果在调用ToUnicodeEx()之前键盘状态已经被用户敲下了死锁键修改,则返回的字符串将包含预期值之前的死键字符。 我找到的解决方法是在实际调用之前用空格键的扫描码调用ToUnicodeEx()。
希望这个帮助!
看看KeysConverter和它的ConvertToString方法。 请记住,并非所有KeyDown都映射到KeyPress。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。