自主控制软键盘,避免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();
        }
    }

posted on 2022-05-22 21:46  TanZhiWei  阅读(262)  评论(0编辑  收藏  举报