一 引入

项目有个需求,需要实现纯触控操作进行键盘输入。项目部署在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. day01--MarkDown语法格式

    MarkDown语法格式 标题 一级标题 一级标题: 井号+空格+标题名字 二级标题 二级标题: 双井号+空格+标题名字 三级标题 三级标题: 三井号+空格+标题名字 ......... 字体 斜体( ...

  2. 网易云UI模仿-->侧边栏

    侧边栏 效果图 界面分解 可以看到从上到下的流式布局.需要一个Column来容纳,并且在往上滑动的过程中顶部的个人信息是不会动的.所以接下来需要将剩余部分占满使用Flexibel组件. 实现 个人信息 ...

  3. angular 变化检测和ngZone

  4. 8000字讲透OBSA原理与应用实践

    摘要:OBSA项目是围绕OBS建立的大数据和AI生态,其在不断的发展和完善中,目前有如下子项目:hadoop-obs项目和flink-obs项目. 文章作者:存储服务产品部开发者支持团队 OBS存储服 ...

  5. 鸟枪换炮,利用python3对球员做大数据降维(因子分析得分),为C罗找到合格僚机

    鸟枪换炮,利用python3对球员做大数据降维(因子分析得分),为C罗找到合格僚机 原文转载自「刘悦的技术博客」https://v3u.cn/a_id_176 众所周知,尤文图斯需要一座欧冠奖杯,C罗 ...

  6. Dart 异步编程(一):初步认识

    由于 Dart 是单线程编程语言,对于进行网络请求和I/O操作,线程将发生阻塞,严重影响依赖于此任务的下一步操作. 通常,在一个阻塞任务之后还有许许多多的任务等待被执行.下一步任务需要上一步任务的结果 ...

  7. React报错之React Hook 'useEffect' is called in function

    正文从这开始~ 总览 为了解决错误"React Hook 'useEffect' is called in function that is neither a React function ...

  8. 理想汽车 x JuiceFS:从 Hadoop 到云原生的演进与思考

    理想汽车在 Hadoop 时代的技术架构 首先简单回顾下大数据技术的发展,基于我个人的理解,将大数据的发展分了4个时期: 第一个时期: 2006 年到 2008 年.2008 年左右,Hadoop 成 ...

  9. 小A的树 - 树形DP

    题面 1 9 4 4 1 1 5 1 2 3 2 3 6 6 7 6 8 9 6 0 1 0 1 0 0 1 0 1 3 2 7 3 4 0 9 5 YES YES NO NO 题解 n <= ...

  10. ASP.NET Core 6框架揭秘实例演示[34]:缓存整个响应内容

    我们利用ASP.NET开发的大部分API都是为了对外提供资源,对于不易变化的资源内容,针对某个维度对其实施缓存可以很好地提供应用的性能.<内存缓存与分布式缓存的使用>介绍的两种缓存框架(本 ...