【问题标题】:How to send WM_INPUTLANGCHANGEREQUEST to app with modal window?如何使用模态窗口将 WM_INPUTLANGCHANGEREQUEST 发送到应用程序?
【发布时间】:2018-06-30 19:21:43
【问题描述】:

我写了一个键盘切换器,效果很好,但是如果当前应用程序打开了模态窗口,它就会失败。在键盘开关上,我执行以下操作

hwnd = GetForegroundWindow();
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, handle);

在哪里

[DllImport("User32.dll", EntryPoint = "PostMessage")]
private static extern int PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();

但语言没有改变。

我将如何做到这一点?


添加 get root owner 改善了情况,但没有完全帮助。

添加对GetDesktopWindow 的呼叫没有帮助:

hwnd = GetDesktopWindow();
InputLangChangeRequest(hwnd, language);
hwnd = GetRootOwner();
InputLangChangeRequest(hwnd, language);

代码在这里https://github.com/dims12/NormalKeyboardSwitcher

【问题讨论】:

标签: c# winapi modal-dialog postmessage


【解决方案1】:

使用GetAncestor

通过遍历父和链来检索拥有的根窗口 GetParent 返回的所有者窗口。

如果有模态窗口或模态窗口链,这应该返回主 UI 窗口。

hwnd = GetForegroundWindow();
hwnd = GetAncestor(hwnd, GA_ROOTOWNER); //#define GA_ROOTOWNER 3


如果目标本身是基于对话框的应用程序,显然WM_INPUTLANGCHANGEREQUEST 会失败(我不知道为什么!)要解决问题,您可以将WM_INPUTLANGCHANGEREQUEST 消息发布到对话框的后代(除了WM_INPUTLANGCHANGEREQUEST 消息到对话框本身)
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);
    }
}

【讨论】:

  • 没有帮助。可能是任务相反?需要找到最深的后代窗口,而不是祖先?
  • 我用 WinSpy++ 检查了窗口句柄,发现:(1)上面的序列错误地找到了窗口,(2)如果我依赖其他进程(跟踪前台窗口更改)并获得相同的十六进制句柄,发送消息仍然不会切换语言
  • 我部分错了:句柄在两个方向都是正确的(不正确的 hadnler 是由于切换到调试器),但语言仍然没有改变。
  • 我以为你说它在窗口顶部没有模式对话框时有效。因此,如果GetAncestor 返回正确的窗口句柄,它应该可以工作。我用记事本测试了这个。当记事本的关于对话框处于活动状态时,它也可以工作。使用LoadKeyboardLayout("00000408", KLF_ACTIVATE) 进行测试。请注意,这只会更改键盘语言。
  • 是的,你是对的,我已经检查过了,它适用于Notepad 中的模态窗口(文件->打开)。但是如果应用程序只有一个窗口并且它是模态的(Pageant
猜你喜欢
  • 1970-01-01
  • 2013-08-03
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
相关资源
最近更新 更多