项目有个需求,需要实现纯触控操作进行键盘输入。项目部署在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);
}
}
下图为demo效果:
当TextBox获取焦点时,弹出键盘。当TextBox失去焦点时,隐藏键盘。
点击键盘的右上角的关闭键或Esc键隐藏键盘。
因项目不需要全键位,所有针对性地对键位进行了删减和排列。
使用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的前台代码。
注:其中按钮的样式是自己的控件库中实现的,未贴出。
<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>
下附Demo界面后台代码。
///
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界面的前台代码。
虚拟键码 (Winuser.h) - Win32 apps | Microsoft Docs
手机扫一扫
移动阅读更方便
你可能感兴趣的文章