MSDN示例库: C#创建一个软键盘

Create a soft keyboard

翻译: 白水<敏捷学院>

 原文链接:http://dev.mjxy.cn/a-csharp-to-create-a-soft-keyboard.aspx

下载源代码:CSSoftKeyboard.zip

 

Windows应用程序:CSSoftKeyboard 软键盘

摘要

该示例演示如何创建一个软键盘。它具有以下特点

  1. 当一个按钮被按下时它不会获得焦点。
  2. 如果用户按下鼠标左键,在其非工作区(如标题栏),它会被激活。当鼠标左键被释放时,它会激活以前的前台窗口。
  3. 当用户单击一个字母的时候,例如 "A" 或者 "1",它将发送键到当前激活的程序。
  4. 提供特殊键的支持,例如 "WinKey" "Delete"。
  5. 提供组合键的支持,例如 "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"键,你将会看到记事本显示保存对话框。

代码逻辑

  1. 设计一个 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);

       }

  1. 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]));

  1. KeyBoardForm是键盘的主要处理类。当窗体被加载的时候它会载入KeysMapping.xml来初始化键盘按钮。

参考文献:

posted @ 2011-07-20 12:10  敏捷学院  阅读(1196)  评论(0编辑  收藏  举报