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

Windows 10通用应用:TextBox获焦自动打开触摸键盘解决方案咨询

我刚好之前在做WPF触摸设备适配时解决过完全一样的问题,给你两个实用的方案,都是纯C#/WPF实现,完美满足“文本框获焦自动开键盘、失焦自动关”的需求:

方案一:基于TabTip.exe的快速实现(适合大多数WPF桌面应用)

首先澄清一点:你提到的“Windows通用应用没有Process库”是针对UWP应用的,WPF桌面应用(不管是.NET Framework还是.NET 5+)完全可以正常使用System.Diagnostics.Process,所以这个方案是可行的。

我们可以用WPF的附加行为(Attached Behavior)来实现全局复用,不用给每个文本框单独写事件:

步骤1:创建触摸键盘自动控制的附加行为

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;

public static class TouchKeyboardBehavior
{
    // 调用Windows API查找窗口和发送关闭消息
    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    private const uint WM_SYSCOMMAND = 0x0112;
    private const uint SC_CLOSE = 0xF060;

    // 定义附加属性
    public static readonly DependencyProperty AutoShowTouchKeyboardProperty =
        DependencyProperty.RegisterAttached(
            "AutoShowTouchKeyboard",
            typeof(bool),
            typeof(TouchKeyboardBehavior),
            new PropertyMetadata(false, OnAutoShowTouchKeyboardChanged));

    public static bool GetAutoShowTouchKeyboard(DependencyObject obj)
    {
        return (bool)obj.GetValue(AutoShowTouchKeyboardProperty);
    }

    public static void SetAutoShowTouchKeyboard(DependencyObject obj, bool value)
    {
        obj.SetValue(AutoShowTouchKeyboardProperty, value);
    }

    // 属性变化时绑定/解绑焦点事件
    private static void OnAutoShowTouchKeyboardChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is TextBox textBox)
        {
            if ((bool)e.NewValue)
            {
                textBox.GotFocus += TextBox_GotFocus;
                textBox.LostFocus += TextBox_LostFocus;
            }
            else
            {
                textBox.GotFocus -= TextBox_GotFocus;
                textBox.LostFocus -= TextBox_LostFocus;
            }
        }
    }

    // 获焦时启动触摸键盘
    private static void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        try
        {
            // 启动TabTip,UseShellExecute确保能正确找到路径
            Process.Start(new ProcessStartInfo("TabTip.exe") { UseShellExecute = true });
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"启动触摸键盘失败: {ex.Message}");
            // 若找不到TabTip,可尝试使用完整路径:C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe
        }
    }

    // 失焦时关闭触摸键盘(用PostMessage模拟用户关闭,比Kill更安全)
    private static void TextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        IntPtr tabTipWnd = FindWindow("IPTip_Main_Window", null);
        if (tabTipWnd != IntPtr.Zero)
        {
            PostMessage(tabTipWnd, WM_SYSCOMMAND, (IntPtr)SC_CLOSE, IntPtr.Zero);
        }
    }
}

步骤2:在XAML中使用

在你的Window/UserControl里声明命名空间(替换成你的项目命名空间),然后给需要的文本框添加附加属性:

<Window xmlns:local="clr-namespace:YourAppNamespace">
    <TextBox local:TouchKeyboardBehavior.AutoShowTouchKeyboard="True" 
             Width="200" Height="30" />
</Window>

注意事项

  • 这个方案兼容绝大多数Windows 10/11版本,若TabTip启动失败,可直接写完整路径
  • 用PostMessage关闭而不是Process.Kill,避免影响其他依赖触摸键盘的系统功能
方案二:调用原生触摸键盘API(更可靠的长期方案)

如果担心TabTip.exe的路径兼容性,可以直接调用Windows触摸键盘的COM接口,这是系统原生的控制方式,稳定性更好:

步骤1:实现原生API调用的附加行为

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;

// 导入触摸键盘的COM接口
[ComImport, Guid("37c994e7-432b-4834-a2f7-dce1f13b834b")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITipInvocation
{
    void Toggle(IntPtr hwnd);
}

[ComImport, Guid("4ce576fa-83dc-4F88-951c-9d0782b4e376")]
public class TouchKeyboardComObject
{
}

public static class TouchKeyboardApiBehavior
{
    public static readonly DependencyProperty AutoShowProperty =
        DependencyProperty.RegisterAttached(
            "AutoShow",
            typeof(bool),
            typeof(TouchKeyboardApiBehavior),
            new PropertyMetadata(false, OnAutoShowChanged));

    public static bool GetAutoShow(DependencyObject obj)
    {
        return (bool)obj.GetValue(AutoShowProperty);
    }

    public static void SetAutoShow(DependencyObject obj, bool value)
    {
        obj.SetValue(AutoShowProperty, value);
    }

    private static void OnAutoShowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is TextBox textBox)
        {
            if ((bool)e.NewValue)
            {
                textBox.GotFocus += TextBox_GotFocus;
                textBox.LostFocus += TextBox_LostFocus;
            }
            else
            {
                textBox.GotFocus -= TextBox_GotFocus;
                textBox.LostFocus -= TextBox_LostFocus;
            }
        }
    }

    private static void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        if (sender is TextBox textBox)
        {
            try
            {
                var windowHandle = new WindowInteropHelper(Window.GetWindow(textBox)).Handle;
                var tipInvocation = (ITipInvocation)new TouchKeyboardComObject();
                tipInvocation.Toggle(windowHandle); // 显示触摸键盘
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"显示触摸键盘失败: {ex.Message}");
            }
        }
    }

    private static void TextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        try
        {
            var tipInvocation = (ITipInvocation)new TouchKeyboardComObject();
            tipInvocation.Toggle(IntPtr.Zero); // 隐藏触摸键盘
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine($"隐藏触摸键盘失败: {ex.Message}");
        }
    }
}

步骤2:XAML中使用

和方案一一样,添加命名空间后给文本框设置属性:

<TextBox local:TouchKeyboardApiBehavior.AutoShow="True" 
         Width="200" Height="30" />

方案优势

  • 直接和系统触摸键盘交互,不受TabTip.exe路径变化影响
  • 支持更精确的控制,比如可以判断当前键盘状态再执行操作
额外扩展建议
  • 你可以把行为扩展到PasswordBox、RichTextBox等其他输入控件,只需要把代码里的TextBox替换成Control,并判断控件是否支持文本输入
  • 如果是在非触摸设备上运行,这些代码不会报错,只是触摸键盘不会显示

内容的提问来源于stack exchange,提问作者Mr. Developer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:01:09