在和小伙伴一起解决问题的时候,遇到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();
}
}