一 引入

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

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

二 调用Win10自带的触摸键盘

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

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);
}
}

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

下图为demo效果:

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

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

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



3.1 SoftKeyboardControl控件

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

    /// <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[code];
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();
}
}

下附SoftKeyboardControl的前台代码。

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

<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>

3.2 Demo界面的代码

下附Demo界面后台代码。

/// <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;
}
}

下附Demo界面的前台代码。

<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>

四 参考链接

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

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

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

WPF开发经验-实现Win10虚拟触摸键盘的更多相关文章

  1. 示例:WPF仿制OSK做的系统键盘和数字键盘

    原文:示例:WPF仿制OSK做的系统键盘和数字键盘 一.目的:在应用osk.exe系统键盘时遇到很多不方便,比如有些系统调用不出来等问题,由此开发了一个系统键盘仿制osk 二.实现功能 1.目前实现大 ...

  2. WPF中实现自定义虚拟容器(实现VirtualizingPanel)

    WPF中实现自定义虚拟容器(实现VirtualizingPanel) 在WPF应用程序开发过程中,大数据量的数据展现通常都要考虑性能问题.有下面一种常见的情况:原始数据源数据量很大,但是某一时刻数据容 ...

  3. thinkpad彻底消除"触摸键盘"图标

    输入“服务”,进入“查看本地服务”,找到“Touch Keyboard and Handwriting Panel Service”, 将其启动类型改为“禁用”,这样的话重启电脑之后也不会自动启动这触 ...

  4. Android StatusBarUtil:设置Android系统下方虚拟键键盘透明度

     Android StatusBarUtil:设置Android系统下方虚拟键键盘透明度 Android StatusBarUtil是github上的一个开源项目,主页:https://githu ...

  5. T470 Win10下触摸板手势

    T470 Win10下触摸板手势 学习了:https://forum.51nb.com/thread-1742490-1-1.html 三指横向竟然是alt+tab 学习了:http://www.xi ...

  6. mac安装win10后触摸板没有右键功能键的添加技巧

    一些mac用户也会在自己的笔记本电脑上安装windows10系统. 但最近有部分用户发现,安装上win10正式版后,发现无论点击触摸板哪个位置,都只有左键,根本无法右键的问题, 针对此问题,现笔者分享 ...

  7. C# WPF 中用代码模拟鼠标和键盘的操作

    原文:C# WPF 中用代码模拟鼠标和键盘的操作 原文地址 C#开发者都知道,在Winform开发中,SendKeys类提供的方法是很实用的.但是可惜的是,在WPF中不能使用这个方法了. 我们知道,在 ...

  8. WPF DispatcherTimer(定时器应用) 无人触摸60s自动关闭窗口

    原文:WPF DispatcherTimer(定时器应用) 无人触摸60s自动关闭窗口 如果无人触摸:60s自动关闭窗口 xmal:部分 <s:SurfaceWindow x:Class=&qu ...

  9. 【wpf】在win10系统上弹出toast和notification

    原文:[wpf]在win10系统上弹出toast和notification 老规矩,先看效果 右下角的notification: 操作中心的notification: 整体效果: 前提条件 1.需要在 ...

随机推荐

  1. Go语言基础一:环境配置与基础语法

    配置开发环境 开始使用Go,首先需要一个完善的开发环境. 下载并安装Go 安装包的下载地址为:https://golang.org/dl/ go语言中文社区下载:https://studygolang ...

  2. 开发中常用的两个JSON方法

    参考文章:https://juejin.cn/post/6844903711127404557 在前端开发过程中,有两个非常有用的方法来处理 JSON 格式的内容: JSON.parse(string ...

  3. 学会使用MySQL的Explain执行计划,SQL性能调优从此不再困难

    上篇文章讲了MySQL架构体系,了解到MySQL Server端的优化器可以生成Explain执行计划,而执行计划可以帮助我们分析SQL语句性能瓶颈,优化SQL查询逻辑,今天就一块学习Explain执 ...

  4. html的基础01

    1.什么是网页 2.常用的浏览器有哪些 3.web标准是什么  1.什么是网页  2.常用的浏览器 360.百度那些都是国产浏览器,内核一样,以上六个都是国际浏览器,不同厂商生产(但IE和Edge都是 ...

  5. Nginx 文件传输效率、实时、压缩配置指令

    # sendfile 开启文件高效传输模式 # 默认值:off # 位置:http.servcer.location-- # 开启和不开启worker访问的文件发送到浏览器的过程不同. # 不开启的时 ...

  6. 痞子衡嵌入式:聊聊i.MXRT1170双核下不同GPIO组的访问以及中断设计

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170双核下不同GPIO组的访问以及中断设计. 在双核 i.MXRT1170 下设计应用程序,有一个比较重要的考虑点就是外 ...

  7. Luogu5367 【模板】康托展开 (康拓展开)

    \(n^2\)暴力 #include <iostream> #include <cstdio> #include <cstring> #include <al ...

  8. DS二叉树——二叉树之数组存储

    题目描述 二叉树可以采用数组的方法进行存储,把数组中的数据依次自上而下,自左至右存储到二叉树结点中,一般二叉树与完全二叉树对比,比完全二叉树缺少的结点就在数组中用0来表示.,如下图所示 从上图可以看出 ...

  9. 神器 利器 Typora

    用typora编辑真的实在太爽了! gooooooooooooooooooooooooooooooood! 支持html可以实现好看的排版! 支持latex实在是太棒了! 不过默认不支持,要去首选项里 ...

  10. 在微信小程序中,如何获取 for 循环的 index

    微信小程序中,for 循环的 index(索引值)可以用wx:for-index="index"来获取. <view class="item" wx:fo ...