我在更改键盘挂钩内的键盘布局时遇到问题。在这个简单的代码中,当按下“A”键时,需要花费很多时间来更改语言,在更复杂的情况下,应用程序会做错误的事情。
应用程序在托盘中工作,因此我使用了钩子。 我的代码有什么问题? ))或者,也许有不同的方式来改变键盘布局,这适用于钩子?谢谢你的回答。
private static bool nextKey = false;
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
uint tpid = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
ushort currentLayout = GetKeyboardLayout(tpid);
if (nCode >= 0 && wParam == (IntPtr) WM_KEYDOWN) {
if (nextKey) {
Console.WriteLine("changing to english...");
PostMessage(GetForegroundWindow(), 0x0050, 0, (int) LoadKeyboardLayout("00000409", 0x00000001));
nextKey = false;
}
int vkCode = Marshal.ReadInt32(lParam);
if (vkCode == 0x41 && currentLayout == 0x409) { // if language is rus and 'A' pressed
Console.WriteLine("changing to russian...");
PostMessage(GetForegroundWindow(), 0x0050, 0, (int) LoadKeyboardLayout("00000419", 0x00000001));
nextKey = true;
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
答案 0 :(得分:0)
在尝试修复此代码之前,我不得不提出几个愚蠢的问题:
现在,专门查看您的代码,您正在做的是将WM_INPUTLANGCHANGEREQUEST
消息发布到前台窗口。但是此消息是通知。它通知程序用户请求更改输入语言。它的目的不是允许程序向其他程序发出更改输入语言的请求。
如果程序想要更改自己的键盘布局,则会调用ActivateKeyboardLayout
函数。但是没有必要从.NET应用程序调用此函数。该框架已经将所有这些内容包含在强烈推荐的InputLanguage
类中。
除此之外,其他问题不可避免地存在于您未展示的代码中,代码属于其他应用程序。发布WM_INPUTLANGCHANGEREQUEST
消息的前台窗口可以选择通过将消息传递到DefWindowProc
来接受更改,或者通过在响应中返回0来拒绝更改。 If a broken application just返回0 for all those messages it does not explicitly process,它不会做正确的事情。或者,如果某个应用程序已被编写为明确拒绝WM_INPUTLANGCHANGEREQUEST
个请求,那么它将无法满足您的期望。等等。你无法控制这些事情。请记住,WM_INPUTLANGCHANGEREQUEST
只是一个请求。
就速度问题而言("需要花费很多时间,更改语言"),首次加载输入语言并不能保证是一个快速的操作。我看到使用普通机制在我的机器上延迟了半秒钟。通常不是一个大瓶颈;大多数人不会多次来回切换。如果您确实需要加快速度,请考虑缓存LoadKeyboardLayout
函数的返回值。