微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将键码转换为相关的显示字符

一个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] 举报,一经查实,本站将立刻删除。

相关推荐