WPF Popup中IME不跟随TextBox

WPF Popup中IME不跟随TextBox

在 WPF 程序中,如果一个 TextBox 被放置在 Popup 中,当在这个 TextBox 中进行输入时,输入法(IME) 的备选框不会显示在该 TextBox 旁边,而是显示在 Windows 右下角,如下动图所示。

如果 TextBox 是直接放置在 Window(或其子控件)之上的,IME 会呈跟随 TextBox 呈现。

此乃 WPF 的已知 BUG,原因在于 Popup 和 Window 类似,拥有自己的句柄和焦点管理,而此处的 Poupup 没有获得 Win32 焦点(焦点仍停留在父窗口上),所以 IME 位置不正确。
解决办法是,当 Popup 获得 WPF 焦点时,通过 Windows SetFocus API 来设置 Win32 焦点。可以监听 Popup 的 GotFocus 事件来执行 SetFocus 操作:

[DllImport("User32.dll")]
private static extern IntPtr SetFocus(IntPtr hWnd);
 
private void MyPopup_GotFocus(object sender, RoutedEventArgs e)
{
    var source = (HwndSource)PresentationSource.FromVisual(MyPopup.Child);
    if (source != null)
    {
        SetFocus(source.Handle);
    }
}

如上操作可能会导致焦点非预期,需要根据实际情况稍作处理。例如,需要两次点击 TextBox 才能使其获得焦点,可加如下代码来解决:

var source = (HwndSource)PresentationSource.FromVisual(MyPopup.Child);
if (source != null)
{
    SetFocus(source.Handle);
    MyTextBox.Focus();  // 解决需要两次点击 TextBox 才能获取焦点的问题
}

最终效果如下图所示,即使 TextBox 在 Popup 中,IME 也能呈现在 TextBox 旁边。

另外,你还可能遇到 Popup 中的 TextBox 无法切换输入法、无法输入中文等问题,可参考:IME can’t be turned on for TextBoxes inside a Popup

参考资料

猜你喜欢

转载自blog.csdn.net/Iron_Ye/article/details/82831356