WPF中禁用Win10自动弹出屏幕键盘,实现点击文本框唤出
手动控制WPF中文本框触发Win10屏幕键盘的解决方案
我之前也踩过WPF和Win10系统自带屏幕键盘兼容的大坑——明明在系统设置里开了非平板模式自动弹出,但在多文本框的WPF应用里要么闪一下就消失,要么完全没反应,触摸屏设备上这个问题尤其突出。后来索性放弃系统自动逻辑,手动控制键盘的弹出和关闭,亲测稳定好用,分享给你:
核心思路
直接调用Windows自带的屏幕键盘程序osk.exe,通过WPF文本框的焦点事件来触发启动/前置操作,同时处理重复启动、窗口遮挡等细节问题。
实现步骤
1. 绑定文本框的焦点事件
在XAML里给需要触发键盘的文本框绑定GotFocus(获得焦点)和LostFocus(失去焦点)事件:
<Window x:Class="WpfOskDemo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF屏幕键盘测试" Height="450" Width="800"> <StackPanel Margin="20"> <TextBox x:Name="txtUsername" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus" Margin="0 0 0 10" /> <TextBox x:Name="txtPassword" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus" Margin="0 0 0 10" /> <TextBox x:Name="txtAddress" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus" /> </StackPanel> </Window>
2. 后台代码实现键盘控制
在C#后台代码中处理事件,实现启动、前置、关闭屏幕键盘的逻辑,同时加入触摸屏设备判断(可选):
using System; using System.Diagnostics; using System.Linq; using System.Windows; using System.Windows.Input; namespace WpfOskDemo { public partial class MainWindow : Window { private Process _oskProcess; public MainWindow() { InitializeComponent(); } private void TextBox_GotFocus(object sender, RoutedEventArgs e) { // 可选:仅在触摸屏设备上触发,非触摸屏设备跳过 if (!Tablet.TabletDevices.OfType<TabletDevice>().Any(t => t.Type == TabletDeviceType.Touch)) { return; } // 检查键盘是否已运行 if (_oskProcess == null || _oskProcess.HasExited) { try { // 启动屏幕键盘,使用ShellExecute避免权限问题 var startInfo = new ProcessStartInfo { FileName = "osk.exe", UseShellExecute = true, WindowStyle = ProcessWindowStyle.Normal }; _oskProcess = Process.Start(startInfo); } catch (Exception ex) { MessageBox.Show($"启动屏幕键盘失败:{ex.Message}"); } } else { // 键盘已运行,将其前置显示(避免被其他窗口遮挡) if (_oskProcess.MainWindowHandle != IntPtr.Zero) { User32.SetForegroundWindow(_oskProcess.MainWindowHandle); } } } private void TextBox_LostFocus(object sender, RoutedEventArgs e) { // 检查是否还有其他文本框处于焦点状态,没有则关闭键盘 var focusedTextBox = Keyboard.FocusedElement as TextBox; if (focusedTextBox == null) { _oskProcess?.CloseMainWindow(); _oskProcess?.WaitForExit(); _oskProcess = null; } } } // 引入User32.dll的API用于窗口前置 internal static class User32 { [System.Runtime.InteropServices.DllImport("user32.dll")] internal static extern bool SetForegroundWindow(IntPtr hWnd); } }
关键注意事项
- 避免重复启动:一定要检查
_oskProcess的状态,防止多次打开屏幕键盘窗口。 - 权限兼容:使用
UseShellExecute = true启动osk.exe,避免管理员权限运行应用时出现启动失败的问题。 - 窗口遮挡处理:通过
SetForegroundWindow确保键盘窗口显示在最上层,不会被WPF窗口挡住。 - 触摸屏判断:如果你的应用只针对触摸屏设备,可以去掉触摸屏检测的逻辑,直接触发键盘。
内容的提问来源于stack exchange,提问作者lentinant
相关产品推荐
相关产品推荐

