C# 如何使用模式窗口将WM_INPUTLANGCHANGEREQUEST发送到应用程序?
我编写了一个键盘切换器,它工作得很好,但如果当前应用程序打开了模式窗口,它就会失败。在键盘开关上,我执行以下操作C# 如何使用模式窗口将WM_INPUTLANGCHANGEREQUEST发送到应用程序?,c#,winapi,modal-dialog,postmessage,C#,Winapi,Modal Dialog,Postmessage,我编写了一个键盘切换器,它工作得很好,但如果当前应用程序打开了模式窗口,它就会失败。在键盘开关上,我执行以下操作 hwnd = GetForegroundWindow(); PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, handle); 在哪里 但语言并没有改变 我将如何做到这一点 添加get root owner改善了这种情况,但并没有完全起到帮助作用 添加对GetDesktopWindow的调用没有帮助: hwnd =
hwnd = GetForegroundWindow();
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, handle);
在哪里
但语言并没有改变
我将如何做到这一点
添加get root owner改善了这种情况,但并没有完全起到帮助作用 添加对
GetDesktopWindow
的调用没有帮助:
hwnd = GetDesktopWindow();
InputLangChangeRequest(hwnd, language);
hwnd = GetRootOwner();
InputLangChangeRequest(hwnd, language);
代码在这里使用 通过遍历父窗口和子窗口的链来检索拥有的根窗口 GetParent返回的所有者窗口 如果存在模式窗口或模式窗口链,则应返回主UI窗口
hwnd = GetForegroundWindow();
hwnd = GetAncestor(hwnd, GA_ROOTOWNER); //#define GA_ROOTOWNER 3
显然,如果目标本身是基于对话框的应用程序(我不知道为什么!),则
WM\u INPUTLANGCHANGEREQUEST
失败。要解决此问题,您可以将WM\u INPUTLANGCHANGEREQUEST
消息发布到对话框的子体(除了WM\u INPUTLANGCHANGEREQUEST
消息发布到对话框本身)
可能的副本没有帮助。可能任务是相反的?需要找到最深的子代窗口,而不是祖先?我用WinSpy++检查了窗口句柄,发现:(1)上面的序列不正确地找到了窗口;(2)如果我依赖于其他进程(跟踪前景窗口更改)并获得相同的十六进制句柄,发送消息仍然无法切换语言我有部分错误:句柄在两个方面都是正确的(不正确的hadnler是由于切换到调试器),但语言仍然没有更改。我记得您说过,当窗口顶部没有模式对话框时,它可以工作。因此,如果
getconcenter
返回正确的窗口句柄,它应该可以工作。我用记事本测试了这个。当记事本的“关于”对话框处于活动状态时,它也可以工作。使用加载键盘布局(“00000408”,KLF_激活)
进行测试。请注意,这只会更改键盘语言。是的,您是对的,我已经检查过了,它可以与记事本中的模式窗口(文件->打开)一起工作。但若应用程序只有一个窗口并且是模态的(Pageant
),它就不起作用了
hwnd = GetForegroundWindow();
hwnd = GetAncestor(hwnd, GA_ROOTOWNER); //#define GA_ROOTOWNER 3
static bool MyEnumProc(IntPtr hwnd, IntPtr lParam)
{
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, lParam);
return true;
}
static void Foo()
{
//Greek input for testing:
var hkl = LoadKeyboardLayout("00000408", KLF_ACTIVATE);
var hwnd = GetForegroundWindow();
if (hwnd != null)
{
hwnd = GetAncestor(hwnd, GA_ROOTOWNER);
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, (IntPtr)hkl);
StringBuilder buf = new StringBuilder(100);
GetClassName(hwnd, buf, 100);
//if this is a dialog class then post message to all descendants
if (buf.ToString() == "#32770")
EnumChildWindows(hwnd, MyEnumProc, (IntPtr)hkl);
}
}