C# 实现屏幕键盘 (ScreenKeyboard)

C# 实现屏幕键盘 (ScreenKeyboard)

大家好,又见面了,我是全栈君。

要实现一个屏幕键盘,需要监听所有键盘事件,无论窗体是否被激活。因此需要一个全局的钩子,也就
是系统范围的钩子。

什么是钩子(Hook)

钩子(Hook)是Windows提供的一种消息处理机制平台,是指在程序正常运行中接受信息之前预先
启动的函数,用来检查和修改传给该程序的信息,(钩子)实际上是一个处理消息的程序段,通
过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获
该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不
作处理而继续传递该消息,还可以强制结束消息的传递。注意:安装钩子函数将会影响系统的性
能。监测“系统范围事件”的系统钩子特别明显。因为系统在处理所有的相关事件时都将调用您的
钩子函数,这样您的系统将会明显的减慢。所以应谨慎使用,用完后立即卸载。还有,由于您可
以预先截获其它进程的消息,所以一旦您的钩子函数出了问题的话必将影响其它的进程。

钩子的作用范围
一共有两种范围(类型)的钩子,局部的和远程的。局部钩子仅钩挂自己进程的事件。远程的钩
子还可以将钩挂其它进程发生的事件。远程的钩子又有两种: 基于线程的钩子将捕获其它进程中
某一特定线程的事件。简言之,就是可以用来观察其它进程中的某一特定线程将发生的事件。 系
统范围的钩子将捕捉系统中所有进程将发生的事件消息。

Hook 类型
Windows共有14种Hooks,每一种类型的Hook可以使应用程序能够监视不同类型的系统消息处理机
制。下面描述所有可以利用的Hook类型的发生时机。详细内容可以查阅MSDN,这里只介绍我们将要
用到的两种类型的钩子。
(1)WH_KEYBOARD_LL Hook
WH_KEYBOARD_LL Hook监视输入到线程消息队列中的键盘消息。

(2)WH_MOUSE_LL Hook
WH_MOUSE_LL Hook监视输入到线程消息队列中的鼠标消息。

下面的 class 把 API 调用封装起来以便调用。

1C# 实现屏幕键盘 (ScreenKeyboard)// NativeMethods.cs
2C# 实现屏幕键盘 (ScreenKeyboard)using System;
3C# 实现屏幕键盘 (ScreenKeyboard)using System.Runtime.InteropServices;
4C# 实现屏幕键盘 (ScreenKeyboard)using System.Drawing;
5C# 实现屏幕键盘 (ScreenKeyboard)
6C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard)namespace CnBlogs.Youzai.ScreenKeyboard C# 实现屏幕键盘 (ScreenKeyboard){
7C# 实现屏幕键盘 (ScreenKeyboard) [StructLayout(LayoutKind.Sequential)]
8C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) internal struct MOUSEINPUT C# 实现屏幕键盘 (ScreenKeyboard){
9C# 实现屏幕键盘 (ScreenKeyboard) public int dx;
10C# 实现屏幕键盘 (ScreenKeyboard) public int dy;
11C# 实现屏幕键盘 (ScreenKeyboard) public int mouseData;
12C# 实现屏幕键盘 (ScreenKeyboard) public int dwFlags;
13C# 实现屏幕键盘 (ScreenKeyboard) public int time;
14C# 实现屏幕键盘 (ScreenKeyboard) public IntPtr dwExtraInfo;
15C# 实现屏幕键盘 (ScreenKeyboard) }
16C# 实现屏幕键盘 (ScreenKeyboard)
17C# 实现屏幕键盘 (ScreenKeyboard) [StructLayout(LayoutKind.Sequential)]
18C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) internal struct KEYBDINPUT C# 实现屏幕键盘 (ScreenKeyboard){
19C# 实现屏幕键盘 (ScreenKeyboard) public short wVk;
20C# 实现屏幕键盘 (ScreenKeyboard) public short wScan;
21C# 实现屏幕键盘 (ScreenKeyboard) public int dwFlags;
22C# 实现屏幕键盘 (ScreenKeyboard) public int time;
23C# 实现屏幕键盘 (ScreenKeyboard) public IntPtr dwExtraInfo;
24C# 实现屏幕键盘 (ScreenKeyboard) }
25C# 实现屏幕键盘 (ScreenKeyboard)
26C# 实现屏幕键盘 (ScreenKeyboard) [StructLayout(LayoutKind.Explicit)]
27C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) internal struct Input C# 实现屏幕键盘 (ScreenKeyboard){
28C# 实现屏幕键盘 (ScreenKeyboard) [FieldOffset(0)]
29C# 实现屏幕键盘 (ScreenKeyboard) public int type;
30C# 实现屏幕键盘 (ScreenKeyboard) [FieldOffset(4)]
31C# 实现屏幕键盘 (ScreenKeyboard) public MOUSEINPUT mi;
32C# 实现屏幕键盘 (ScreenKeyboard) [FieldOffset(4)]
33C# 实现屏幕键盘 (ScreenKeyboard) public KEYBDINPUT ki;
34C# 实现屏幕键盘 (ScreenKeyboard) [FieldOffset(4)]
35C# 实现屏幕键盘 (ScreenKeyboard) public HARDWAREINPUT hi;
36C# 实现屏幕键盘 (ScreenKeyboard) }
37C# 实现屏幕键盘 (ScreenKeyboard)
38C# 实现屏幕键盘 (ScreenKeyboard) [StructLayout(LayoutKind.Sequential)]
39C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) internal struct HARDWAREINPUT C# 实现屏幕键盘 (ScreenKeyboard){
40C# 实现屏幕键盘 (ScreenKeyboard) public int uMsg;
41C# 实现屏幕键盘 (ScreenKeyboard) public short wParamL;
42C# 实现屏幕键盘 (ScreenKeyboard) public short wParamH;
43C# 实现屏幕键盘 (ScreenKeyboard) }
44C# 实现屏幕键盘 (ScreenKeyboard)
45C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) internal class INPUT C# 实现屏幕键盘 (ScreenKeyboard){
46C# 实现屏幕键盘 (ScreenKeyboard) public const int MOUSE = 0;
47C# 实现屏幕键盘 (ScreenKeyboard) public const int KEYBOARD = 1;
48C# 实现屏幕键盘 (ScreenKeyboard) public const int HARDWARE = 2;
49C# 实现屏幕键盘 (ScreenKeyboard) }
50C# 实现屏幕键盘 (ScreenKeyboard)
51C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) internal static class NativeMethods C# 实现屏幕键盘 (ScreenKeyboard){
52C# 实现屏幕键盘 (ScreenKeyboard) [DllImport(“User32.dll”, CharSet = CharSet.Auto, SetLastError = false)]
53C# 实现屏幕键盘 (ScreenKeyboard) internal static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
54C# 实现屏幕键盘 (ScreenKeyboard)
55C# 实现屏幕键盘 (ScreenKeyboard) [DllImport(“User32.dll”, CharSet = CharSet.Auto, SetLastError = false)]
56C# 实现屏幕键盘 (ScreenKeyboard) internal static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
57C# 实现屏幕键盘 (ScreenKeyboard)
58C# 实现屏幕键盘 (ScreenKeyboard) [DllImport(“User32.dll”, EntryPoint = “SendInput”, CharSet = CharSet.Auto)]
59C# 实现屏幕键盘 (ScreenKeyboard) internal static extern UInt32 SendInput(UInt32 nInputs, Input[] pInputs, Int32 cbSize);
60C# 实现屏幕键盘 (ScreenKeyboard)
61C# 实现屏幕键盘 (ScreenKeyboard) [DllImport(“Kernel32.dll”, EntryPoint = “GetTickCount”, CharSet = CharSet.Auto)]
62C# 实现屏幕键盘 (ScreenKeyboard) internal static extern int GetTickCount();
63C# 实现屏幕键盘 (ScreenKeyboard)
64C# 实现屏幕键盘 (ScreenKeyboard) [DllImport(“User32.dll”, EntryPoint = “GetKeyState”, CharSet = CharSet.Auto)]
65C# 实现屏幕键盘 (ScreenKeyboard) internal static extern short GetKeyState(int nVirtKey);
66C# 实现屏幕键盘 (ScreenKeyboard)
67C# 实现屏幕键盘 (ScreenKeyboard) [DllImport(“User32.dll”, EntryPoint = “SendMessage”, CharSet = CharSet.Auto)]
68C# 实现屏幕键盘 (ScreenKeyboard) internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
69C# 实现屏幕键盘 (ScreenKeyboard) }
70C# 实现屏幕键盘 (ScreenKeyboard)}

安装钩子
使用SetWindowsHookEx函数(API函数),指定一个Hook类型、自己的Hook过程是全局还是局部Hook,
同时给出Hook过程的进入点,就可以轻松的安装自己的Hook过程。SetWindowsHookEx总是将你的Hook函
数放置在Hook链的顶端。你可以使用CallNextHookEx函数将系统消息传递给Hook链中的下一个函数。
对于某些类型的Hook,系统将向该类的所有Hook函数发送消息,这时,
Hook函数中的CallNextHookEx语句将被忽略。全局(远程钩子)Hook函数可以拦截系统中所有线程的某
个特定的消息,为了安装一个全局Hook过程,必须在应用程序外建立一个DLL并将该Hook函数封装到其中,
应用程序在安装全局Hook过程时必须先得到该DLL模块的句柄。将Dll名传递给LoadLibrary 函数,就会得
到该DLL模块的句柄;得到该句柄 后,使用GetProcAddress函数可以得到Hook过程的地址。最后,使用
SetWindowsHookEx将 Hook过程的首址嵌入相应的Hook链中,SetWindowsHookEx传递一个模块句柄,它为
Hook过程的进入点,线程标识符置为0,该Hook过程同系统中的所有线程关联。如果是安装局部Hook此时
该Hook函数可以放置在DLL中,也可以放置在应用程序的模块段。在C#中通过平台调用(前文已经介绍过)
来调用API函数。

1C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) public void Start(bool installMouseHook, bool installKeyboardHook) C# 实现屏幕键盘 (ScreenKeyboard){
2C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (hMouseHook == IntPtr.Zero && installMouseHook) C# 实现屏幕键盘 (ScreenKeyboard){
3C# 实现屏幕键盘 (ScreenKeyboard) MouseHookProcedure = new HookProc(MouseHookProc);
4C# 实现屏幕键盘 (ScreenKeyboard) hMouseHook = SetWindowsHookEx(
5C# 实现屏幕键盘 (ScreenKeyboard) WH_MOUSE_LL,
6C# 实现屏幕键盘 (ScreenKeyboard) MouseHookProcedure,
7C# 实现屏幕键盘 (ScreenKeyboard) Marshal.GetHINSTANCE(
8C# 实现屏幕键盘 (ScreenKeyboard) Assembly.GetExecutingAssembly().GetModules()[0]),
9C# 实现屏幕键盘 (ScreenKeyboard) 0
10C# 实现屏幕键盘 (ScreenKeyboard) );
11C# 实现屏幕键盘 (ScreenKeyboard)
12C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (hMouseHook == IntPtr.Zero) C# 实现屏幕键盘 (ScreenKeyboard){
13C# 实现屏幕键盘 (ScreenKeyboard) int errorCode = Marshal.GetLastWin32Error();
14C# 实现屏幕键盘 (ScreenKeyboard) Stop(true, false, false);
15C# 实现屏幕键盘 (ScreenKeyboard)
16C# 实现屏幕键盘 (ScreenKeyboard) throw new Win32Exception(errorCode);
17C# 实现屏幕键盘 (ScreenKeyboard) }
18C# 实现屏幕键盘 (ScreenKeyboard) }
19C# 实现屏幕键盘 (ScreenKeyboard)
20C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (hKeyboardHook == IntPtr.Zero && installKeyboardHook) C# 实现屏幕键盘 (ScreenKeyboard){
21C# 实现屏幕键盘 (ScreenKeyboard) KeyboardHookProcedure = new HookProc(KeyboardHookProc);
22C# 实现屏幕键盘 (ScreenKeyboard) //install hook
23C# 实现屏幕键盘 (ScreenKeyboard) hKeyboardHook = SetWindowsHookEx(
24C# 实现屏幕键盘 (ScreenKeyboard) WH_KEYBOARD_LL,
25C# 实现屏幕键盘 (ScreenKeyboard) KeyboardHookProcedure,
26C# 实现屏幕键盘 (ScreenKeyboard) Marshal.GetHINSTANCE(
27C# 实现屏幕键盘 (ScreenKeyboard) Assembly.GetExecutingAssembly().GetModules()[0]),
28C# 实现屏幕键盘 (ScreenKeyboard) 0);
29C# 实现屏幕键盘 (ScreenKeyboard) // If SetWindowsHookEx fails.
30C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (hKeyboardHook == IntPtr.Zero) C# 实现屏幕键盘 (ScreenKeyboard){
31C# 实现屏幕键盘 (ScreenKeyboard) // Returns the error code returned by the last
32C# 实现屏幕键盘 (ScreenKeyboard) // unmanaged function called using platform invoke
33C# 实现屏幕键盘 (ScreenKeyboard) // that has the DllImportAttribute.SetLastError flag set.
34C# 实现屏幕键盘 (ScreenKeyboard) int errorCode = Marshal.GetLastWin32Error();
35C# 实现屏幕键盘 (ScreenKeyboard) //do cleanup
36C# 实现屏幕键盘 (ScreenKeyboard) Stop(false, true, false);
37C# 实现屏幕键盘 (ScreenKeyboard) //Initializes and throws a new instance of the
38C# 实现屏幕键盘 (ScreenKeyboard) // Win32Exception class with the specified error.
39C# 实现屏幕键盘 (ScreenKeyboard) throw new Win32Exception(errorCode);
40C# 实现屏幕键盘 (ScreenKeyboard) }
41C# 实现屏幕键盘 (ScreenKeyboard) }
42C# 实现屏幕键盘 (ScreenKeyboard) }

使用完钩子后,要进行卸载,这个可以写在析构函数中。

1C# 实现屏幕键盘 (ScreenKeyboard)
2C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) public void Stop() C# 实现屏幕键盘 (ScreenKeyboard){
3C# 实现屏幕键盘 (ScreenKeyboard) this.Stop(true, true, true);
4C# 实现屏幕键盘 (ScreenKeyboard) }
5C# 实现屏幕键盘 (ScreenKeyboard)
6C# 实现屏幕键盘 (ScreenKeyboard) public void Stop(bool uninstallMouseHook, bool uninstallKeyboardHook,
7C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) bool throwExceptions) C# 实现屏幕键盘 (ScreenKeyboard){
8C# 实现屏幕键盘 (ScreenKeyboard) // if mouse hook set and must be uninstalled
9C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (hMouseHook != IntPtr.Zero && uninstallMouseHook) C# 实现屏幕键盘 (ScreenKeyboard){
10C# 实现屏幕键盘 (ScreenKeyboard) // uninstall hook
11C# 实现屏幕键盘 (ScreenKeyboard) bool retMouse = UnhookWindowsHookEx(hMouseHook);
12C# 实现屏幕键盘 (ScreenKeyboard) // reset invalid handle
13C# 实现屏幕键盘 (ScreenKeyboard) hMouseHook = IntPtr.Zero;
14C# 实现屏幕键盘 (ScreenKeyboard) // if failed and exception must be thrown
15C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (retMouse == false && throwExceptions) C# 实现屏幕键盘 (ScreenKeyboard){
16C# 实现屏幕键盘 (ScreenKeyboard) // Returns the error code returned by the last unmanaged function
17C# 实现屏幕键盘 (ScreenKeyboard) // called using platform invoke that has the DllImportAttribute.
18C# 实现屏幕键盘 (ScreenKeyboard) // SetLastError flag set.
19C# 实现屏幕键盘 (ScreenKeyboard) int errorCode = Marshal.GetLastWin32Error();
20C# 实现屏幕键盘 (ScreenKeyboard) // Initializes and throws a new instance of the Win32Exception class
21C# 实现屏幕键盘 (ScreenKeyboard) // with the specified error.
22C# 实现屏幕键盘 (ScreenKeyboard) throw new Win32Exception(errorCode);
23C# 实现屏幕键盘 (ScreenKeyboard) }
24C# 实现屏幕键盘 (ScreenKeyboard) }
25C# 实现屏幕键盘 (ScreenKeyboard)
26C# 实现屏幕键盘 (ScreenKeyboard) // if keyboard hook set and must be uninstalled
27C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (hKeyboardHook != IntPtr.Zero && uninstallKeyboardHook) C# 实现屏幕键盘 (ScreenKeyboard){
28C# 实现屏幕键盘 (ScreenKeyboard) // uninstall hook
29C# 实现屏幕键盘 (ScreenKeyboard) bool retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
30C# 实现屏幕键盘 (ScreenKeyboard) // reset invalid handle
31C# 实现屏幕键盘 (ScreenKeyboard) hKeyboardHook = IntPtr.Zero;
32C# 实现屏幕键盘 (ScreenKeyboard) // if failed and exception must be thrown
33C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (retKeyboard == false && throwExceptions) C# 实现屏幕键盘 (ScreenKeyboard){
34C# 实现屏幕键盘 (ScreenKeyboard) // Returns the error code returned by the last unmanaged function
35C# 实现屏幕键盘 (ScreenKeyboard) // called using platform invoke that has the DllImportAttribute.
36C# 实现屏幕键盘 (ScreenKeyboard) // SetLastError flag set.
37C# 实现屏幕键盘 (ScreenKeyboard) int errorCode = Marshal.GetLastWin32Error();
38C# 实现屏幕键盘 (ScreenKeyboard) // Initializes and throws a new instance of the Win32Exception class
39C# 实现屏幕键盘 (ScreenKeyboard) // with the specified error.
40C# 实现屏幕键盘 (ScreenKeyboard) throw new Win32Exception(errorCode);
41C# 实现屏幕键盘 (ScreenKeyboard) }
42C# 实现屏幕键盘 (ScreenKeyboard) }
43C# 实现屏幕键盘 (ScreenKeyboard) }
44C# 实现屏幕键盘 (ScreenKeyboard)

将这个文件编译成一个dll,即可在应用程序中调用。通过它提供的事件,便可监听所有的键盘事件。
但是,这只能监听键盘事件,没有键盘的情况下,怎么会有键盘事件?其实很简单,通过SendInput
API函数提供虚拟键盘代码的调用即可模拟键盘输入。下面的代码模拟一个 KeyDown 和 KeyUp 过程,
把他们连接起来就是一次按键过程。

1C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) private void SendKeyDown(short key) C# 实现屏幕键盘 (ScreenKeyboard){
2C# 实现屏幕键盘 (ScreenKeyboard) Input[] input = new Input[1];
3C# 实现屏幕键盘 (ScreenKeyboard) input[0].type = INPUT.KEYBOARD;
4C# 实现屏幕键盘 (ScreenKeyboard) input[0].ki.wVk = key;
5C# 实现屏幕键盘 (ScreenKeyboard) input[0].ki.time = NativeMethods.GetTickCount();
6C# 实现屏幕键盘 (ScreenKeyboard)
7C# 实现屏幕键盘 (ScreenKeyboard) if (NativeMethods.SendInput((uint)input.Length, input, Marshal.SizeOf(input[0]))
8C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) < input.Length) C# 实现屏幕键盘 (ScreenKeyboard){
9C# 实现屏幕键盘 (ScreenKeyboard) throw new Win32Exception(Marshal.GetLastWin32Error());
10C# 实现屏幕键盘 (ScreenKeyboard) }
11C# 实现屏幕键盘 (ScreenKeyboard) }
12C# 实现屏幕键盘 (ScreenKeyboard)
13C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) private void SendKeyUp(short key) C# 实现屏幕键盘 (ScreenKeyboard){
14C# 实现屏幕键盘 (ScreenKeyboard) Input[] input = new Input[1];
15C# 实现屏幕键盘 (ScreenKeyboard) input[0].type = INPUT.KEYBOARD;
16C# 实现屏幕键盘 (ScreenKeyboard) input[0].ki.wVk = key;
17C# 实现屏幕键盘 (ScreenKeyboard) input[0].ki.dwFlags = KeyboardConstaint.KEYEVENTF_KEYUP;
18C# 实现屏幕键盘 (ScreenKeyboard) input[0].ki.time = NativeMethods.GetTickCount();
19C# 实现屏幕键盘 (ScreenKeyboard)
20C# 实现屏幕键盘 (ScreenKeyboard) if (NativeMethods.SendInput((uint)input.Length, input, Marshal.SizeOf(input[0]))
21C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) < input.Length) C# 实现屏幕键盘 (ScreenKeyboard){
22C# 实现屏幕键盘 (ScreenKeyboard) throw new Win32Exception(Marshal.GetLastWin32Error());
23C# 实现屏幕键盘 (ScreenKeyboard) }
24C# 实现屏幕键盘 (ScreenKeyboard) }

自己实现一个 KeyBoardButton 控件用作按钮,用 Visual Studio 或者 SharpDevelop 为屏幕键盘设计 UI,然后
在这些 Button 的 Click 事件里面模拟一个按键过程。

1C# 实现屏幕键盘 (ScreenKeyboard)
2C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) private void ButtonOnClick(object sender, EventArgs e) C# 实现屏幕键盘 (ScreenKeyboard){
3C# 实现屏幕键盘 (ScreenKeyboard) KeyboardButton btnKey = sender as KeyboardButton;
4C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (btnKey == null) C# 实现屏幕键盘 (ScreenKeyboard){
5C# 实现屏幕键盘 (ScreenKeyboard) return;
6C# 实现屏幕键盘 (ScreenKeyboard) }
7C# 实现屏幕键盘 (ScreenKeyboard)
8C# 实现屏幕键盘 (ScreenKeyboard) SendKeyCommand(btnKey);
9C# 实现屏幕键盘 (ScreenKeyboard) }
10C# 实现屏幕键盘 (ScreenKeyboard)
11C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) private void SendKeyCommand(KeyboardButton keyButton) C# 实现屏幕键盘 (ScreenKeyboard){
12C# 实现屏幕键盘 (ScreenKeyboard) short key = keyButton.VKCode;
13C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (combinationVKButtonsMap.ContainsKey(key)) C# 实现屏幕键盘 (ScreenKeyboard){
14C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (keyButton.Checked) C# 实现屏幕键盘 (ScreenKeyboard){
15C# 实现屏幕键盘 (ScreenKeyboard) SendKeyUp(key);
16C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) } else C# 实现屏幕键盘 (ScreenKeyboard){
17C# 实现屏幕键盘 (ScreenKeyboard) SendKeyDown(key);
18C# 实现屏幕键盘 (ScreenKeyboard) }
19C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) } else C# 实现屏幕键盘 (ScreenKeyboard){
20C# 实现屏幕键盘 (ScreenKeyboard) SendKeyDown(key);
21C# 实现屏幕键盘 (ScreenKeyboard) SendKeyUp(key);
22C# 实现屏幕键盘 (ScreenKeyboard) }
23C# 实现屏幕键盘 (ScreenKeyboard) }

其中 combinationVKButtonsMap 是一个 IDictionary<short, IList<KeyboardButton>>, key 存储的是
VK_SHIFT, VK_CONTROL 等组合键的键盘码。左右两个按钮对应同一个键盘码,因此需要放在一个 List 里。
标准键盘上的每一个键都有虚拟键码( VK_CODE)与之对应。还有一些其他的常量,
把它写在一个静态 class 里吧。

1C# 实现屏幕键盘 (ScreenKeyboard) // KeyboardConstaint.cs
2C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) internal static class KeyboardConstaint C# 实现屏幕键盘 (ScreenKeyboard){
3C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F1 = 0x70;
4C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F2 = 0x71;
5C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F3 = 0x72;
6C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F4 = 0x73;
7C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F5 = 0x74;
8C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F6 = 0x75;
9C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F7 = 0x76;
10C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F8 = 0x77;
11C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F9 = 0x78;
12C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F10 = 0x79;
13C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F11 = 0x7A;
14C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_F12 = 0x7B;
15C# 实现屏幕键盘 (ScreenKeyboard)
16C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_LEFT = 0x25;
17C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_UP = 0x26;
18C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_RIGHT = 0x27;
19C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_DOWN = 0x28;
20C# 实现屏幕键盘 (ScreenKeyboard)
21C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NONE = 0x00;
22C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_ESCAPE = 0x1B;
23C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_EXECUTE = 0x2B;
24C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_CANCEL = 0x03;
25C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_RETURN = 0x0D;
26C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_ACCEPT = 0x1E;
27C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_BACK = 0x08;
28C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_TAB = 0x09;
29C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_DELETE = 0x2E;
30C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_CAPITAL = 0x14;
31C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMLOCK = 0x90;
32C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_SPACE = 0x20;
33C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_DECIMAL = 0x6E;
34C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_SUBTRACT = 0x6D;
35C# 实现屏幕键盘 (ScreenKeyboard)
36C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_ADD = 0x6B;
37C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_DIVIDE = 0x6F;
38C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_MULTIPLY = 0x6A;
39C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_INSERT = 0x2D;
40C# 实现屏幕键盘 (ScreenKeyboard)
41C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_1 = 0xBA; // ‘;:’ for US
42C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_PLUS = 0xBB; // ‘+’ any country
43C# 实现屏幕键盘 (ScreenKeyboard)
44C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_MINUS = 0xBD; // ‘-‘ any country
45C# 实现屏幕键盘 (ScreenKeyboard)
46C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_2 = 0xBF; // ‘/?’ for US
47C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_3 = 0xC0; // ‘`~’ for US
48C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_4 = 0xDB; // ‘[{‘ for US
49C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_5 = 0xDC; // ‘\|’ for US
50C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_6 = 0xDD; // ‘]}’ for US
51C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_7 = 0xDE; // ””‘ for US
52C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_PERIOD = 0xBE; // ‘.>’ any country
53C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_OEM_COMMA = 0xBC; // ‘,<‘ any country
54C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_SHIFT = 0x10;
55C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_CONTROL = 0x11;
56C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_MENU = 0x12;
57C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_LWIN = 0x5B;
58C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_RWIN = 0x5C;
59C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_APPS = 0x5D;
60C# 实现屏幕键盘 (ScreenKeyboard)
61C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_LSHIFT = 0xA0;
62C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_RSHIFT = 0xA1;
63C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_LCONTROL = 0xA2;
64C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_RCONTROL = 0xA3;
65C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_LMENU = 0xA4;
66C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_RMENU = 0xA5;
67C# 实现屏幕键盘 (ScreenKeyboard)
68C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_SNAPSHOT = 0x2C;
69C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_SCROLL = 0x91;
70C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_PAUSE = 0x13;
71C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_HOME = 0x24;
72C# 实现屏幕键盘 (ScreenKeyboard)
73C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NEXT = 0x22;
74C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_PRIOR = 0x21;
75C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_END = 0x23;
76C# 实现屏幕键盘 (ScreenKeyboard)
77C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD0 = 0x60;
78C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD1 = 0x61;
79C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD2 = 0x62;
80C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD3 = 0x63;
81C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD4 = 0x64;
82C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD5 = 0x65;
83C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD5NOTHING = 0x0C;
84C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD6 = 0x66;
85C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD7 = 0x67;
86C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD8 = 0x68;
87C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short VK_NUMPAD9 = 0x69;
88C# 实现屏幕键盘 (ScreenKeyboard)
89C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short KEYEVENTF_EXTENDEDKEY = 0x0001;
90C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly short KEYEVENTF_KEYUP = 0x0002;
91C# 实现屏幕键盘 (ScreenKeyboard)
92C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly int GWL_EXSTYLE = -20;
93C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly int WS_DISABLED = 0X8000000;
94C# 实现屏幕键盘 (ScreenKeyboard) internal static readonly int WM_SETFOCUS = 0X0007;
95C# 实现屏幕键盘 (ScreenKeyboard) }

屏幕键盘必须是一个不能获得输入焦点的窗体,在这个窗体的构造函数里,可以安装
一个全局鼠标钩子,再通过调用 SetWindowLong API 函数完成。

1C# 实现屏幕键盘 (ScreenKeyboard)UserActivityHook hook = new UserActivityHook(true, true);
2C# 实现屏幕键盘 (ScreenKeyboard)hook.MouseActivity += HookOnMouseActivity;
3C# 实现屏幕键盘 (ScreenKeyboard)
4C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard)private void HookOnMouseActivity(object sener, HookEx.MouseExEventArgs e) C# 实现屏幕键盘 (ScreenKeyboard){
5C# 实现屏幕键盘 (ScreenKeyboard) Point location = e.Location;
6C# 实现屏幕键盘 (ScreenKeyboard)
7C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (e.Button == MouseButtons.Left) C# 实现屏幕键盘 (ScreenKeyboard){
8C# 实现屏幕键盘 (ScreenKeyboard) Rectangle captionRect = new Rectangle(this.Location, new Size(this.Width,
9C# 实现屏幕键盘 (ScreenKeyboard) SystemInformation.CaptionHeight));
10C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) if (captionRect.Contains(location)) C# 实现屏幕键盘 (ScreenKeyboard){
11C# 实现屏幕键盘 (ScreenKeyboard) NativeMethods.SetWindowLong(this.Handle, KeyboardConstaint.GWL_EXSTYLE,
12C# 实现屏幕键盘 (ScreenKeyboard) (int)NativeMethods.GetWindowLong(this.Handle, KeyboardConstaint.GWL_EXSTYLE)
13C# 实现屏幕键盘 (ScreenKeyboard) & (~KeyboardConstaint.WS_DISABLED));
14C# 实现屏幕键盘 (ScreenKeyboard) NativeMethods.SendMessage(this.Handle, KeyboardConstaint.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
15C# 实现屏幕键盘 (ScreenKeyboard)C# 实现屏幕键盘 (ScreenKeyboard) } else C# 实现屏幕键盘 (ScreenKeyboard){
16C# 实现屏幕键盘 (ScreenKeyboard) NativeMethods.SetWindowLong(this.Handle, KeyboardConstaint.GWL_EXSTYLE,
17C# 实现屏幕键盘 (ScreenKeyboard) (int)NativeMethods.GetWindowLong(this.Handle, KeyboardConstaint.GWL_EXSTYLE) |
18C# 实现屏幕键盘 (ScreenKeyboard) KeyboardConstaint.WS_DISABLED);
19C# 实现屏幕键盘 (ScreenKeyboard) }
20C# 实现屏幕键盘 (ScreenKeyboard) }
21C# 实现屏幕键盘 (ScreenKeyboard)}

鼠标单击标题栏,让屏幕键盘可以接收焦点,并激活,单击其他部分则不激活窗体(如果激活了,其他程序必然取消激活,
输入就无法进行了),这样才可以进行输入,并且保证了可以拖动窗体到其他位置。

至此,一个屏幕键盘程序差不多完成了,能够实现与实际键盘完全同步。至于窗体,按键重绘,以及 Num Lock, Caps Lock,

本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2009/09/04/1560008.html,如需转载请自行联系原作者 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107882.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • vue 图片上传 图片展示 bootstrap

    vue 图片上传 图片展示 bootstrap效果图html…………<--key=idPicUrl-->

    2022年6月22日
    39
  • Zigbee协议栈中文说明

    Zigbee协议栈中文说明1.概述 1.1解析ZigBee堆栈架构ZigBee堆栈是在IEEE802.15.4标准基础上建立的,定义了协议的MAC和PHY层。ZigBee设备应该包括IEEE802.15.4(该标准定义了RF射频以及与相邻设备之间的通信)的PHY和MAC层,以及ZigBee堆栈层:网络层(NWK)、应用层和安全服务提供层。图1-1给出了这些组件的概况。1.1.1ZigBee堆栈层每个Z

    2022年5月8日
    40
  • Python-matplotlib画图(莫烦笔记)

    https://www.zhihu.com/collection/260736383&lt;此处就不自己写了,看了遍,照着写了一边,作者写的不错。不过有些有些偷懒,我只做了常见的功能&gt;作者:触摸壹缕阳光链接:https://zhuanlan.zhihu.com/p/33270402来源:知乎著作权归作者所有,转载请联系作者获得授权。1.前言Matplotlib是一个python的2D绘图库…

    2022年4月4日
    37
  • cheerio 笔记

    cheerio 笔记简介 cheerio 是一个 node 的库 可以理解为一个 Node js 版本的 jquery 用来从网页中以 cssselector 取数据 使用方式和 jquery 基本相同 npminstallch require cheerio var cheerio load lt h2class title gt Hellowo

    2025年11月20日
    2
  • navicat15激活工具【最新永久激活】2022.01.21[通俗易懂]

    (navicat15激活工具)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月31日
    81
  • SecureCRT的使用方法和技巧(详细使用教程)[通俗易懂]

    SecureCRT的使用方法和技巧(详细使用教程)[通俗易懂]随时随地阅读更多技术实战干货,获取项目源码、学习资料,请关注源代码社区公众号(ydmsq666)SecureCRT是最常用的终端仿真程序,简单的说就是Windows下登录UNIX或Liunx服务器主机的软件,本文主要介绍SecureCRT的使用方法和技巧VanDykeCRT和VanDyke…

    2022年6月7日
    59

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号