C# 中自定义的屏幕键盘





5.00/5 (6投票s)
Windows 的 C# 中自定义的屏幕键盘。
引言
如果您曾为触摸屏设备开发过软件,您就知道屏幕键盘是一个必不可少的组件。Windows 提供了屏幕键盘作为其内置的辅助功能工具之一。
Windows OSK 是一个解决方案,但您对其功能和行为的控制能力非常有限,更不用说添加新任务了!
在本文中,我将展示构建 Windows 屏幕键盘和自定义它的基本方法。
背景
我曾为多个软件应用程序构建过屏幕键盘,但从未制作过一个功能齐全的、包含 101 多个按键的键盘。在最近的一个项目中,我们需要集成一个完整的屏幕键盘,并且可以对其进行控制。
因此,我投入了这项工作,您在此处看到的是我工作的成果。您可以对其进行扩展并根据您的需求进行构建。
核心方法
构建屏幕键盘的“关键”是使用 SendKeys.Send
方法
SendKeys.Send(string)
此方法将按键发送到活动应用程序。例如,如果您想单击一个按钮并发送 TAB
按键,可以使用以下方法:
SendKeys.Send("{TAB}");
如果您的请求不代表有效的按键,您的代码将收到一个 ArgumentException
。
注释
- 有时,您需要发送多个字符才能获得特定的按键。
例如,要指定左括号符号,请使用“
{{}
”。SendKeys.Send("{}}");
- 加号 (+)、插入符 (^)、百分号 (%)、波浪号 (~) 和括号 () 对
SendKeys
具有特殊含义。要指定这些字符之一,请将其括在花括号({})
中。 - 要指定按下按键时不会显示的字符,例如 **ENTER** 或 **TAB**,以及代表操作而非字符的按键,您必须使用特定的代码。
例如
SendKeys.Send("{MULTIPLY}"); //The Multiply key on the number keypad
SendKeys.Send("{ADD}"); //The Add key on the number keypad
处理 SHIFT、CTRL 和 ALT
组合键,如 **CTRL + Key**、**SHIFT + Key** 和 **ALT + Key**,可以通过使用插入符 (^)、加号 (+) 和百分号 (%) 来实现。
要指定在按下 S 时按住 **CTRL**,然后按下 D 而不按 **SHIFT**,请使用“**^SD**”。
要指定按住 **SHIFT** 并按下 **A 和 B**,请使用“**+(AB)**”。
SendKeys.Send("^({F10})"); //CTRL + F10
SendKeys.Send("+({F10})"); //Shift + F10
SendKeys.Send("%({F10})"); //ALT + F10
规划键盘布局
我决定采用我的物理键盘的布局
我在 Visual Studio 中使用 .NET Framework 创建了一个新的 C# Winforms 项目。
我根据物理键盘布局添加了我的按键
对于大多数按键,您可以使用按钮控件,但以下特殊按键需要使用 CheckBox
控件:
CAPSLOCK
SHIFT
CTRL
ALT
NUM LOCK
因此,当 **CAPSLOCK** 键处于开启模式时,您会有一个选中的 CheckBox
来标识大写字母。**CAPSLOCK** 关闭时,会生成小写字母的按键。
对于带有两个字符的按键,例如 2(@)或 7(&),我们需要检查 **SHIFT** 按钮的状态并相应地生成正确的按键。
**SHIFT + 2** 应该发送 @
符号。
类似的情况适用于组合键,例如 **CTRL + C**(复制)、**CTRL + P**(粘贴)等。
if (capslock.Checked || lshift.Checked || rshift.Checked)
{
SendKeys.Send("B"); lshift.Checked = false; rshift.Checked = false;
}
else {
SendKeys.Send("b");
}
为了识别任何复选框是否处于选中状态,我使用了背景颜色
if (capslock.Checked == true)
{
capslock.BackColor = System.Drawing.ColorTranslator.FromHtml("#0076D7");
}
else
capslock.BackColor = System.Drawing.ColorTranslator.FromHtml("#333333");
自定义按键
现在我对屏幕键盘有了完全的控制,我想添加自定义按键。将自定义按键视为在一次按键中发送两个或更多字符的快捷方式。
一些额外的美化细节包括添加一行带有 **CAPS**、**Insert** 和 **NUM LOCK** 键状态的指示。我根据相应按键的开启或关闭状态更改 **CAPS** 和 **NUM** 标签的可见性。我还添加了代码,以便在鼠标悬停在按键上时更改按键的背景颜色。
边框样式问题
如果从窗体属性中选择 FormBorderStyle
的 **None** 选项,您将无法在屏幕上移动键盘并更改其位置。
如果您不介意标准的 Windows 边框,您可以选择最适合您的品味和键盘使用方式的选项。
我想摆脱边框并拥有自己的边框样式。所以这就是我所做的:
- 我将
FormBorderStyle
设置为None
- 将所有按键放置在一个
panel
中,该panel
位于主窗体上 - 更改窗体的背景颜色,以便与
panel
的背景颜色形成对比
现在我有了我的颜色和临时的边框,但我该如何移动我的屏幕键盘呢?
这里的技巧需要一个 Win32 API
[DllImportAttribute("user32.dll")] public static extern int SendMessage
(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")] public static extern bool ReleaseCapture();
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
完成了!
我拥有一个具有自定义背景和边框样式的屏幕键盘,我可以将其移动到屏幕上并添加自定义按键。
关注点
在进行此项目时,我产生了许多想法,可以将普通的屏幕键盘扩展成更多功能。自定义按键是我在此代码中实现的一个功能。
历史
- 2021年8月9日:此代码的首次发布
我希望有机会再次从事这个项目,并可能将其移植到 Xamarin。