You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免WPF弹窗在触摸键盘弹出时自动关闭?

解决WPF Popup因触摸键盘弹出而意外关闭的问题

核心思路

通过Windows API检测当前激活的窗口是否为系统触摸键盘(OSK),在Popup即将因失去焦点关闭时,若判断是触摸键盘导致的焦点转移,则阻止Popup关闭;其他情况保持原有的“失去焦点即关闭”行为。

实现步骤

1. 导入Windows API函数

在窗口类中添加以下DllImport声明,用于获取当前激活窗口及其类名:

using System.Runtime.InteropServices;
using System.Text;

// 获取前台窗口句柄
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

// 获取指定窗口的类名
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

2. 编写触摸键盘检测方法

添加辅助方法判断当前激活窗口是否为系统触摸键盘:

private bool IsOnScreenKeyboardActive()
{
    const int maxClassNameLength = 256;
    var classNameBuilder = new StringBuilder(maxClassNameLength);
    IntPtr activeWindowHandle = GetForegroundWindow();

    // 获取当前激活窗口的类名
    if (GetClassName(activeWindowHandle, classNameBuilder, maxClassNameLength) > 0)
    {
        // 系统触摸键盘的固定窗口类名为 "IPTip_Main_Window"
        return classNameBuilder.ToString() == "IPTip_Main_Window";
    }
    return false;
}

3. 拦截Popup的焦点丢失事件

修改Popup的PreviewLostKeyboardFocus事件处理逻辑,结合检测结果控制Popup状态:

private void Popup_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    var popup = (Popup)sender;
    if (IsOnScreenKeyboardActive())
    {
        // 焦点转移到触摸键盘时,阻止事件传递并强制保持Popup打开
        e.Handled = true;
        popup.StaysOpen = true;
    }
    else
    {
        // 其他情况恢复原行为,允许Popup关闭
        popup.StaysOpen = false;
    }
}

4. 补充外部点击关闭逻辑

为确保点击非触摸键盘区域时Popup正常关闭,添加PreviewMouseDownOutsideCapturedElement事件处理:

private void Popup_PreviewMouseDownOutsideCapturedElement(object sender, MouseButtonEventArgs e)
{
    ((Popup)sender).IsOpen = false;
}

注意事项

  • 初始需将Popup的StaysOpen属性设为False,保证基础的失去焦点关闭行为。
  • 触摸键盘的窗口类名在主流Windows版本中均为IPTip_Main_Window,若后续系统版本变更需同步调整该值。

内容的提问来源于stack exchange,提问作者Daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:13:13