WPF开发经验-实现Win10虚拟触摸键盘

  • A+
所属分类:.NET技术
摘要

项目有个需求,需要实现纯触控操作进行键盘输入。项目部署在Win10系统上,考虑有两种方案来实现。


一 引入

项目有个需求,需要实现纯触控操作进行键盘输入。项目部署在Win10系统上,考虑有两种方案来实现。

  1. 通过调用Win10自带的触摸键盘来实现;
  2. 通过WPF实现一个触摸键盘来实现;

二 调用Win10自带的触摸键盘

简单附上一个调用Win10系统的TabTip.exe的操作类。

WPF开发经验-实现Win10虚拟触摸键盘WPF开发经验-实现Win10虚拟触摸键盘

public class TabTipHelper {     private const int WM_SYSCOMMAND = 274;     private const uint SC_CLOSE = 61536;     private const uint SC_RESTORE = 0xF120;     private const uint SC_MAXIMIZE = 0xF030;     private const uint SC_MINIMIZE = 0xF020;      [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]     private static extern bool PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);      [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 bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);      [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]     private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);      [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]     private static extern int RegisterWindowMessage(string lpString);      public static int ShowTaptip()     {         try         {             dynamic file = "C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe";             if (!System.IO.File.Exists(file))                 return -1;             Process.Start(file);             return 1;         }         catch (Exception)         {             return 255;         }     }      public static async Task ShowTaptipAsync()     {         await Task.Run(() => ShowTaptip());     }      public static void CloseTaptip()     {         var touchhWnd = new IntPtr(0);         touchhWnd = FindWindow("IPTip_Main_Window", null);         if (touchhWnd == IntPtr.Zero)             return;         PostMessage(touchhWnd, WM_SYSCOMMAND, SC_CLOSE, 0);     } }

View Code


三 通过WPF实现一个触摸键盘

下图为demo效果:

当TextBox获取焦点时,弹出键盘。当TextBox失去焦点时,隐藏键盘。

点击键盘的右上角的关闭键或Esc键隐藏键盘。

因项目不需要全键位,所有针对性地对键位进行了删减和排列。


 

WPF开发经验-实现Win10虚拟触摸键盘


 

 3.1 SoftKeyboardControl控件

 使用WPF的UserControl实现虚拟键盘,下附SoftKeyboardControl的后台代码。

WPF开发经验-实现Win10虚拟触摸键盘WPF开发经验-实现Win10虚拟触摸键盘

    /// <summary>     /// SoftKeyboardControl.xaml 的交互逻辑     /// </summary>     public partial class SoftKeyboardControl : UserControl     {         /// <summary>         /// Windows提供的一个模拟键盘API。         /// Keybd_event()函数能触发一个按键事件,生成一个 WM_KEYDOWN 或 WM_KEYUP 消息。         /// </summary>         /// <param name="bVk" >按键的虚拟键值</param>         /// <param name= "bScan" >扫描码,一般不用设置,用0代替就行</param>         /// <param name= "dwFlags" >选项标志:0:表示按下,2:表示松开</param>         /// <param name= "dwExtraInfo">一般设置为0</param>         [DllImport("User32.dll")]         public static extern void keybd_event(byte bVK, byte bScan, int dwFlags, int dwExtraInfo);          public SoftKeyboardControl()         {             InitializeComponent();             CreateKeys();             KeyCommand = new RoutedCommand();             CommandBinding cmdBinding = new CommandBinding(KeyCommand, KeyCommand_Excuted, KeyCommand_CanExcute);             CommandBindings.Add(cmdBinding);         }          #region 虚拟键值          /// <summary>         /// 键和虚拟键值的字典         /// </summary>         private Dictionary<string, byte> keys;          /// <summary>         /// 初始化虚拟键值的字典         /// </summary>         private void CreateKeys()         {             keys = new Dictionary<string, byte>()             {                 #region 数字键盘                  { "0",0x60},                 { "1",0x61},                 { "2",0x62},                 { "3",0x63},                 { "4",0x64},                 { "5",0x65},                 { "6",0x66},                 { "7",0x67},                 { "8",0x68},                 { "9",0x69},                  { "-",0x6d},                 { ".",0x6E},                  #endregion                  #region Q字母行                                { "q", 0x51},                 { "w", 0x57},                 { "e", 0x45},                 { "r", 0x52},                 { "t", 0x54},                 { "y", 0x59},                 { "u", 0x55},                 { "i", 0x49},                 { "o", 0x4f},                 { "p", 0x50},                  { "Q", 0x51},                 { "W", 0x57},                 { "E", 0x45},                 { "R", 0x52},                 { "T", 0x54},                 { "Y", 0x59},                 { "U", 0x55},                 { "I", 0x49},                 { "O", 0x4f},                 { "P", 0x50},                  #endregion                  #region A字母行                  { "a", 0x41},                 { "s", 0x53},                 { "d", 0x44},                 { "f", 0x46},                 { "g", 0x47},                 { "h", 0x48},                 { "j", 0x4A},                 { "k", 0x4B},                 { "l", 0x4C},                  { "A", 0x41},                 { "S", 0x53},                 { "D", 0x44},                 { "F", 0x46},                 { "G", 0x47},                 { "H", 0x48},                 { "J", 0x4A},                 { "K", 0x4B},                 { "L", 0x4C},                  #endregion                  #region Z字母行                  { "z", 0x5A},                 { "x", 0x58},                 { "c", 0x43},                 { "v", 0x56},                 { "b", 0x42},                 { "n", 0x4E},                 { "m", 0x4D},                  { "Z", 0x5A},                 { "X", 0x58},                 { "C", 0x43},                 { "V", 0x56},                 { "B", 0x42},                 { "N", 0x4E},                 { "M", 0x4D},                  #endregion                  #region other                  {"BackSpace",0x08 },                 {"Tab",0x09 },                 {"Enter",0x0d },                 {"Shift",0x10 },                 {"Ctrl",0x11 },                 {"CapsLock",0x14 },                 {"Space",0x20 },                  #endregion             };         }          #endregion          #region DependencyProperty          public static readonly DependencyProperty CapsProperty = DependencyProperty.Register(             "Caps", typeof(bool), typeof(SoftKeyboardControl), new PropertyMetadata(default(bool)));         public bool Caps         {             get { return (bool)GetValue(CapsProperty); }             set { SetValue(CapsProperty, value); }         }          public static readonly DependencyProperty CtrlProperty = DependencyProperty.Register(             "Ctrl", typeof(bool), typeof(SoftKeyboardControl), new PropertyMetadata(default(bool)));          public bool Ctrl         {             get { return (bool)GetValue(CtrlProperty); }             set { SetValue(CtrlProperty, value); }         }          public static readonly DependencyProperty ShiftProperty = DependencyProperty.Register(             "Shift", typeof(bool), typeof(SoftKeyboardControl), new PropertyMetadata(default(bool)));          public bool Shift         {             get { return (bool)GetValue(ShiftProperty); }             set { SetValue(ShiftProperty, value); }         }          #endregion          #region Command          public ICommand KeyCommand { get; set; }         private void KeyCommand_CanExcute(object sender, CanExecuteRoutedEventArgs e)         {             e.CanExecute = true;         }         private void KeyCommand_Excuted(object sender, ExecutedRoutedEventArgs e)         {             if (e.Parameter != null)             {                 var code = e.Parameter.ToString();                 if (keys.ContainsKey(code))                 {                     byte b = keys;                     try                     {                         keybd_event(b, 0, 0, 0);                     }                     catch (Exception ex)                     {                         Console.WriteLine(ex.Message);                     }                 }             }         }          public ICommand CloseCommand { get; set; }          #endregion          protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)         {             base.OnPropertyChanged(e);             if (e.Property == CapsProperty)             {                 keybd_event(0x14, 0, 0, 0);//按下                 keybd_event(0x14, 0, 2, 0); //抬起             }             else if (e.Property == ShiftProperty)             {                 keybd_event(0x10, 0, 0, 0);                 keybd_event(0x10, 0, 2, 0);             }             else if (e.Property == CtrlProperty)             {                 keybd_event(0x11, 0, 0, 0);                 keybd_event(0x11, 0, 2, 0);             }         }     }      /// <summary>     /// 大小写转换     /// </summary>     public class UpperConverter : IValueConverter     {         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)         {             if (parameter == null)             {                 return "";             }              if (value == null)             {                 return parameter.ToString();             }              if ((bool)value)             {                 return parameter.ToString().ToUpper();             }             else             {                 return parameter.ToString().ToLower();             }         }          public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)         {             throw new NotImplementedException();         }     }

View Code

下附SoftKeyboardControl的前台代码。

注:其中按钮的样式是自己的控件库中实现的,未贴出。

WPF开发经验-实现Win10虚拟触摸键盘WPF开发经验-实现Win10虚拟触摸键盘

<UserControl x:Class="UI.View.SoftKeyboardControl"              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"               xmlns:d="http://schemas.microsoft.com/expression/blend/2008"              xmlns:local="clr-namespace:UI.View"              mc:Ignorable="d"               Background="#E6E6E6">     <UserControl.Resources>         <local:UpperConverter x:Key="UpperConverter"/>     </UserControl.Resources>     <StackPanel Margin="6 0 6 6">         <StackPanel Height="40" Orientation="Horizontal" >             <!--关闭按钮-->         </StackPanel>         <StackPanel Orientation="Horizontal" Margin="0 6 0 0" >             <StackPanel>                 <WrapPanel>                     <Button Content="Esc"  Width="85" Height="Auto" Padding="0"                             Command="{Binding CloseCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}" />                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=q}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=w}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=e}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=r}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=t}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=y}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=u}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=i}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=o}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=p}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 </WrapPanel>                 <WrapPanel>                     <ToggleButton Width="100" Content="Caps"                              IsChecked="{Binding Caps,Mode=TwoWay,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=a}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=s}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=d}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=f}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=g}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=h}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=j}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=k}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=l}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 </WrapPanel>                 <WrapPanel>                     <ToggleButton Width="115" Padding="-18 0 0 0 " Content="Shift"                              IsChecked="{Binding Shift,Mode=TwoWay,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=z}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=x}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=c}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=v}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=b}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=n}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}},                                         Converter={StaticResource UpperConverter},ConverterParameter=m}"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Width="125" Content="Enter"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 </WrapPanel>                 <WrapPanel>                     <ToggleButton  Width="115" Padding="-28 0 0 0 " Content="Ctrl"                              IsChecked="{Binding Ctrl,Mode=TwoWay,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"/>                     <Button Content="Space" Width="185" Margin="50 0 0 0"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                     <Button Content="BackSpace" Width="170" Margin="50 0 0 0"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                              CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 </WrapPanel>             </StackPanel>             <Grid Width="auto" Height="auto">                 <Grid.RowDefinitions>                     <RowDefinition/>                     <RowDefinition/>                     <RowDefinition/>                     <RowDefinition/>                 </Grid.RowDefinitions>                 <Grid.ColumnDefinitions>                     <ColumnDefinition/>                     <ColumnDefinition/>                     <ColumnDefinition/>                     <ColumnDefinition/>                 </Grid.ColumnDefinitions>                 <Button Content="7"                         Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="8" Grid.Column="1"                           Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="9" Grid.Column="2"                                 Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="4" Grid.Row="1"                          Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="5" Grid.Row="1" Grid.Column="1"                          Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="6" Grid.Row="1" Grid.Column="2"                          Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="1" Grid.Row="2"                           Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="2" Grid.Row="2" Grid.Column="1"                            Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="3" Grid.Row="2" Grid.Column="2"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="-" Grid.Row="3"                             Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="0" Grid.Row="3" Grid.Column="1"                            Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                 <Button Content="." Grid.Row="3" Grid.Column="2"                            Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>                  <Button Content="Esc" Grid.Row="0" Grid.Column="3" Grid.RowSpan="2"  Margin="0,0,0,5" Width="56" Height="Auto" Padding="0"                         Command="{Binding CloseCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}" />                  <Button Grid.Row="2" Grid.Column="3" Grid.RowSpan="2" Height="auto" Width="56"  Margin="0 0 0 4" Padding="0"                          Content="Enter"                         Command="{Binding KeyCommand,RelativeSource={RelativeSource AncestorType={x:Type local:SoftKeyboardControl}}}"                          CommandParameter="{Binding Path=Content,RelativeSource={RelativeSource Self}}"/>             </Grid>         </StackPanel>     </StackPanel> </UserControl>

View Code

3.2 Demo界面的代码

 下附Demo界面后台代码。

WPF开发经验-实现Win10虚拟触摸键盘WPF开发经验-实现Win10虚拟触摸键盘

/// <summary>     /// TestWindow.xaml 的交互逻辑     /// </summary>     public partial class TestWindow : Window     {         public TestWindow()         {             InitializeComponent();              softKeyboard.CloseCommand = new RoutedCommand();             CommandBinding cmdBinding = new CommandBinding(softKeyboard.CloseCommand, CloseCommand_Excuted, CloseCommand_CanExcute);             CommandBindings.Add(cmdBinding);         }          private void CloseCommand_CanExcute(object sender, CanExecuteRoutedEventArgs e)         {            e.CanExecute = popup.IsOpen;         }          private void CloseCommand_Excuted(object sender, ExecutedRoutedEventArgs e)         {             popup.IsOpen = false;             textBox.Focus();         }          private void TextBox_GotFocus(object sender, RoutedEventArgs e)         {             popup.IsOpen = true;         }          private void TextBox_LostFocus(object sender, RoutedEventArgs e)         {             popup.IsOpen = false;         }     }

View Code

下附Demo界面的前台代码。

WPF开发经验-实现Win10虚拟触摸键盘WPF开发经验-实现Win10虚拟触摸键盘

<Window x:Class="UI.View.TestWindow"         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"         mc:Ignorable="d"         xmlns:view="clr-namespace:UI.View"         Title="TestWindow" Height="800" Width="1400">     <Grid x:Name="grid">         <TextBox Margin="415,233,447,0" FontSize="30" Height="62"                    VerticalContentAlignment="Center"  VerticalAlignment="Top"                  GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus"  />         <TextBox x:Name="textBox" Margin="470,343,503,364" />         <Popup  x:Name="popup"                 StaysOpen="True"                 AllowsTransparency="True"                 PopupAnimation="Fade"                 PlacementTarget="{Binding ElementName = grid}"                 Placement="Bottom"                 HorizontalOffset="250"                 VerticalOffset="-280">             <view:SoftKeyboardControl x:Name="softKeyboard"/>         </Popup>     </Grid> </Window>

View Code

 

 四 参考链接

虚拟键码 (Winuser.h) - Win32 apps | Microsoft Docs 

keybd_event函数 (winuser.h) - Win32 应用|微软文档 (microsoft.com)

WPF实现软键盘 - 我是刹那、 - 博客园 (cnblogs.com)