65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 中自定义的屏幕键盘

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2021 年 8 月 9 日

CPOL

4分钟阅读

viewsIcon

30588

downloadIcon

2393

Windows 的 C# 中自定义的屏幕键盘。

引言

如果您曾为触摸屏设备开发过软件,您就知道屏幕键盘是一个必不可少的组件。Windows 提供了屏幕键盘作为其内置的辅助功能工具之一。
Windows OSK 是一个解决方案,但您对其功能和行为的控制能力非常有限,更不用说添加新任务了!

在本文中,我将展示构建 Windows 屏幕键盘和自定义它的基本方法。

背景

我曾为多个软件应用程序构建过屏幕键盘,但从未制作过一个功能齐全的、包含 101 多个按键的键盘。在最近的一个项目中,我们需要集成一个完整的屏幕键盘,并且可以对其进行控制。

因此,我投入了这项工作,您在此处看到的是我工作的成果。您可以对其进行扩展并根据您的需求进行构建。

核心方法

构建屏幕键盘的“关键”是使用 SendKeys.Send 方法

SendKeys.Send(string)

此方法将按键发送到活动应用程序。例如,如果您想单击一个按钮并发送 TAB 按键,可以使用以下方法:

SendKeys.Send("{TAB}");

如果您的请求不代表有效的按键,您的代码将收到一个 ArgumentException

注释

  1. 有时,您需要发送多个字符才能获得特定的按键。

    例如,要指定左括号符号,请使用“{{}”。

    SendKeys.Send("{}}");
  2. 加号 (+)、插入符 (^)、百分号 (%)、波浪号 (~) 和括号 () 对 SendKeys 具有特殊含义。要指定这些字符之一,请将其括在花括号 ({}) 中。
  3. 要指定按下按键时不会显示的字符,例如 **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

规划键盘布局

我决定采用我的物理键盘的布局

Physical Keyboard

我在 Visual Studio 中使用 .NET Framework 创建了一个新的 C# Winforms 项目。
我根据物理键盘布局添加了我的按键

Onscreen Keyboard layout

对于大多数按键,您可以使用按钮控件,但以下特殊按键需要使用 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 边框,您可以选择最适合您的品味和键盘使用方式的选项。

我想摆脱边框并拥有自己的边框样式。所以这就是我所做的:

  1. 我将 FormBorderStyle 设置为 None
  2. 将所有按键放置在一个 panel 中,该 panel 位于主窗体上
  3. 更改窗体的背景颜色,以便与 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。

© . All rights reserved.