自主控制软键盘,避免TextBox 控制软键盘操作
在和小伙伴一起解决问题的时候,遇到TextBox 弹出软键盘后立马消息(以及关闭TextBox 界面时不消失软键盘),导致的原因是禁用软键盘语言切换,并设置英文输入。为啥要设置为英文,需求是输入密码只能输入英文和数字等非中文(这需求感觉有点莫名其妙,很多大软件密码输入也没这方面的禁用呀、汗)。
禁用语言切换:
<Setter Property="InputMethod.PreferredImeState" Value="Off"></Setter> <Setter Property="InputMethod.PreferredImeConversionMode" Value="Fixed"></Setter> <Setter Property="InputMethod.IsInputMethodEnabled" Value="False"></Setter> <Setter Property="InputLanguageManager.InputLanguage" Value="en-US"></Setter>
拜读组内大佬冬哥(WPF 禁用TextBox的触摸后自动弹出虚拟键盘 - 唐宋元明清2188 - 博客园 (cnblogs.com))一篇博客,受益匪浅。
第一步 既然不能灵活控制那么我禁用TextBox内部的控制软键盘好了,从写OnCreateAutomationPeer方法,禁用TextBox调用软键盘;
protected override AutomationPeer OnCreateAutomationPeer() { return new FrameworkElementAutomationPeer(this); }
具体代码:重写TextBox:在获取焦点显示软键盘,失焦关闭软键盘。注意:在软键盘上点击(右上角X)关闭软键盘时,不会触发失焦事件。所以在点击抬起Up的时候需要检测软键盘有没有关闭(为什么是抬起,而不是down检测,因为很多事件和原始系统软件都是Up触发,比例 Click、微软自带输入框弹出软键盘等),关闭则要打开软键盘。
public class TextBoxNoAutoKeyboard : TextBox { protected override AutomationPeer OnCreateAutomationPeer() { return new FrameworkElementAutomationPeer(this); } protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); if (InputHelper.VerifyShowedInputPanel()) return; InputHelper.ShowInputPanel(); } protected override void OnLostFocus(RoutedEventArgs e) { base.OnLostFocus(e); InputHelper.HideInputPanel(); } protected override void OnGotFocus(RoutedEventArgs e) { base.OnGotFocus(e); InputHelper.ShowInputPanel(); } }
第二步: 控制软盘显示和隐藏
public class InputHelper { private const Int32 WM_SYSCOMMAND = 274; private const UInt32 SC_CLOSE = 61536; [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern bool PostMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32")] public static extern bool IsWindowVisible(IntPtr hWnd); /// <summary> /// 显示屏幕键盘 /// </summary> /// <returns></returns> public static bool ShowInputPanel() { try { dynamic file = "C:\\Program Files\\Common Files\\microsoft shared\\ink\\TabTip.exe"; if (!System.IO.File.Exists(file)) return false; Process.Start(file); return true; } catch (Exception) { return true; } } /// <summary> /// 隐藏屏幕键盘 /// </summary> public static void HideInputPanel() { IntPtr touchhWnd = new IntPtr(0); touchhWnd = FindWindow("IPTip_Main_Window", null); if (touchhWnd == IntPtr.Zero) return; PostMessage(touchhWnd, WM_SYSCOMMAND, SC_CLOSE, 0); } /// <summary> /// 已经显示软键盘 /// </summary> /// <returns></returns> public static bool VerifyShowedInputPanel() { IntPtr touchhWnd = new IntPtr(0); touchhWnd = FindWindow("IPTip_Main_Window", null); if (touchhWnd == IntPtr.Zero) return false; return IsWindowVisible(touchhWnd); } }
第三步xaml前端调用:
<Window x:Class="DisplayDemo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:DisplayDemo" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Window.Resources> <Style x:Key="Style.En" TargetType="{x:Type local:TextBoxNoAutoKeyboard}"> <Setter Property="InputMethod.PreferredImeState" Value="Off"></Setter> <Setter Property="InputMethod.PreferredImeConversionMode" Value="Fixed"></Setter> <Setter Property="InputMethod.IsInputMethodEnabled" Value="False"></Setter> <Setter Property="InputLanguageManager.InputLanguage" Value="en-US"></Setter> <Setter Property="Background" Value="White" /> <Setter Property="BorderThickness" Value="1" /> <Setter Property="Padding" Value="4,0" /> <Setter Property="HorizontalContentAlignment" Value="Left" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="FocusVisualStyle" Value="{x:Null}" /> </Style> <Style x:Key="Style.Cn" TargetType="{x:Type local:TextBoxNoAutoKeyboard}"> <Setter Property="Background" Value="White" /> <Setter Property="BorderThickness" Value="1" /> <Setter Property="Padding" Value="4,0" /> <Setter Property="FontSize" Value="14"/> <Setter Property="HorizontalContentAlignment" Value="Left" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="FocusVisualStyle" Value="{x:Null}" /> </Style> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <local:TextBoxNoAutoKeyboard x:Name="En" Style="{StaticResource Style.En}" Grid.Row="0" Width="400" Height="100"></local:TextBoxNoAutoKeyboard> <local:TextBoxNoAutoKeyboard x:Name="Cn" Style="{StaticResource Style.Cn}" Grid.Row="1" Width="400" Height="100"></local:TextBoxNoAutoKeyboard> </Grid> </Window>
第四部:设置Textbox的focus,显示软键盘、
/// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.Loaded += MainWindow_Loaded; } private async void MainWindow_Loaded(object sender, RoutedEventArgs e) { En.Focus(); } }