MSDN示例库: C#创建一个软键盘
Create a soft keyboard
翻译: 白水<敏捷学院>
原文链接:http://dev.mjxy.cn/a-csharp-to-create-a-soft-keyboard.aspx
下载源代码:CSSoftKeyboard.zip
Windows应用程序:CSSoftKeyboard 软键盘
摘要
该示例演示如何创建一个软键盘。它具有以下特点
- 当一个按钮被按下时它不会获得焦点。
- 如果用户按下鼠标左键,在其非工作区(如标题栏),它会被激活。当鼠标左键被释放时,它会激活以前的前台窗口。
- 当用户单击一个字母的时候,例如 "A" 或者 "1",它将发送键到当前激活的程序。
- 提供特殊键的支持,例如 "WinKey" "Delete"。
- 提供组合键的支持,例如 "Ctrl+C"。
注意:CTRL + ALT + DEL是不支持,因为它会导致安全问题。
演示
步骤1. 在vs2010中编译项目。
步骤2. 打开记事本(Notepad.exe)程序,然后运行CSSoftKeyboard.exe。确定Notepad.exe处于当前激活状态。
演示正常的按键操作
步骤3. 单击"a"键后你键看到字母"a"出现在记事本中。
演示Caps Lock
步骤4. 单击 "Caps"键,你将会看到按键的背景变成白色。之后所有按键字母都变成大写的。
步骤5. 在键盘上单击"a"键,你将会看到一个大写的"A"出现在记事本中。
步骤6. 再次单击"Caps"键,你将会看到所有的字母按键将恢复原样变成小写字母。
演示 Win 键
步骤7. 单击"Win"键,Win键的背景变成白色。
步骤8. 再次单击"Win"键,Win键恢复原样,开始菜单被打开。
演示 shift 键
步骤9. 单击左 "shift" 键,左 shift 和右shift键背景同变成白色。所有的按键将显示shift键允许的字符。例如 "="键将显示 "+"。
步骤10. 单击 "+"键,记事本出现"+"字符。之后左右shift键恢复原样,所有按键字符恢复正常状态。
演示组合键
步骤11. 单击左"Ctrl"键,左右"Ctrl"键背景同时变成白色。
步骤12. 单击 "s"键,你将会看到记事本显示保存对话框。
代码逻辑
- 设计一个 NoActivateWindow类继承自主窗体KeyBoardForm。
NoActivateWindow类代表一个不会被激活窗体,直到用户在其非工作区(如标题栏,菜单栏,或窗框)按下鼠标左键。当释放鼠标左键,这个窗口将激活以前的前台窗口。
/// <summary>
/// Set the form style to WS_EX_NOACTIVATE so that it will not get focus.
/// </summary>
protected override CreateParams CreateParams
{
[PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= (int)WS_EX_NOACTIVATE;
return cp;
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCLBUTTONDOWN:
// Get the current foreground window.
var foregroundWindow = UnsafeNativeMethods.GetForegroundWindow();
// If this window is not the current foreground window, then activate
// itself.
if (foregroundWindow != this.Handle)
{
UnsafeNativeMethods.SetForegroundWindow(this.Handle);
// Store the handle of previous foreground window.
if (foregroundWindow != IntPtr.Zero)
{
previousForegroundWindow = foregroundWindow;
}
}
break;
case WM_NCMOUSEMOVE:
// Determine whether previous window still exist. If yes, then
// activate it.
// Note: There is a scenario that the previous window is closed, but
// the same handle is assgined to a new window.
if ( UnsafeNativeMethods.IsWindow(previousForegroundWindow))
{
UnsafeNativeMethods.SetForegroundWindow(previousForegroundWindow);
}
break;
default:
break;
}
base.WndProc(ref m);
}
- KeyboardInput类封装了在user32.dll的方法SendKey和SendInput,用来模拟一个正常的按键事件。它也支持组合键,如“CTRL + C”。
有3中情况被处理:
2.1 单个按键被按下,例如"A"
var inputs = new NativeMethods.INPUT[1];
inputs[0].type = NativeMethods.INPUT_KEYBOARD;
inputs[0].inputUnion.ki.wVk = (short)key;
UnsafeNativeMethods.SendInput(1, inputs, Marshal.SizeOf(inputs[0]));
2.2 修饰键被按下,例如"Ctrl+A"
// To simulate this scenario, the inputs contains the toggling
// modifier keys, pressing the key and releasing modifier keys events.
//
// For example, to simulate Ctrl+C, we have to send 3 inputs:
// 1. Ctrl is pressed.
// 2. C is pressed.
// 3. Ctrl is released.
var inputs = new NativeMethods.INPUT[modifierKeys.Count()*2 + 1];
int i = 0;
// Simulate the toggling the modifier keys.
foreach (var modifierKey in modifierKeys)
{
inputs[i].type = NativeMethods.INPUT_KEYBOARD;
inputs[i].inputUnion.ki.wVk = (short)modifierKey;
i++;
}
// Simulate pressing the key.
inputs[i].type = NativeMethods.INPUT_KEYBOARD;
inputs[i].inputUnion.ki.wVk = (short)key;
i++;
// Simulate releasing the modifier keys.
foreach (var modifierKey in modifierKeys)
{
inputs[i].type = NativeMethods.INPUT_KEYBOARD;
inputs[i].inputUnion.ki.wVk = (short)modifierKey;
inputs[i].inputUnion.ki.dwFlags = NativeMethods.KEYEVENTF_KEYUP;
i++;
}
UnsafeNativeMethods.SendInput((uint)inputs.Length, inputs,
Marshal.SizeOf(inputs[0]));
2.3 切换键被按下,例如 Caps Lock, Num Lock,Scorll Lock
var inputs = new NativeMethods.INPUT[2];
// Press the key.
inputs[0].type = NativeMethods.INPUT_KEYBOARD;
inputs[0].inputUnion.ki.wVk = (short)key;
// Release the key.
inputs[1].type = NativeMethods.INPUT_KEYBOARD;
inputs[1].inputUnion.ki.wVk = (short)key;
inputs[1].inputUnion.ki.dwFlags = NativeMethods.KEYEVENTF_KEYUP;
UnsafeNativeMethods.SendInput(2, inputs, Marshal.SizeOf(inputs[0]));
- KeyBoardForm是键盘的主要处理类。当窗体被加载的时候它会载入KeysMapping.xml来初始化键盘按钮。
参考文献: