C#键盘消息监听
windows是基于消息处理的。比如用户按下了键盘,该消息首先由操作系统接收,再将其发送到当前的应用程序处理。事实上,在操作系统把消息发送到当前的应用程序前,你可以截取该消息,这就是我们通常所说的钩子程序。
说明:
SetWindowsHookEx()设置钩子函数
UnhookWindowsHookEx()取消钩子函数
CallNextHookEx()把消息传递给下一个钩子,如果是最后一个钩子,则把消息返回给操作系统
截取键盘消息实例:
1 vs新建一个项目WindowsMessageHook,类型为Class Library,把KeyboardHook.cs加入工程,编译后,生成WindowsMessageHook.dll
KeyboardHook.cs代码
代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
namespace WindowsMessageHook
{
public delegate IntPtr HookProc(int code, IntPtr wparam, IntPtr lparam);
public enum HookType //枚举,钩子的类型 WindowsMessageHook
{
MsgFilter = -1,
JournalRecord = 0,
JournalPlayback = 1,
Keyboard = 2,
GetMessage = 3,
CallWndProc = 4,
CBT = 5,
SysMsgFilter = 6,
Mouse = 7,
Hardware = 8,
Debug = 9,
Shell = 10,
ForegroundIdle = 11,
CallWndProcRet = 12,
KeyboardLL = 13,
MouseLL = 14
}
[StructLayout(LayoutKind.Sequential)]
public class KeyboardHookStruct
{
public int vkCode; //表示一个在1到254间的虚似键盘码
public int scanCode; //表示硬件扫描码
public int flags;
public int time;
public int dwExtraInfo;
}
public class KeyboardHook
{
private const int WM_KEYDOWN = 0x100;
private const int WM_KEYUP = 0x101;
private IntPtr nextHookPtr; //记录Hook编号
private HookProc hookProc;
[DllImport("User32.dll")]
public static extern void UnhookWindowsHookEx(IntPtr handle);
[DllImport("User32.dll")]
public static extern IntPtr SetWindowsHookEx(int idHook, [MarshalAs(UnmanagedType.FunctionPtr)] HookProc lpfn, IntPtr hinstance, int threadID);
[DllImport("User32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr handle, int code, IntPtr wparam, IntPtr lparam);
public KeyboardHook()
{
nextHookPtr = IntPtr.Zero;
}
public void SetKeyboardHook()
{
if (nextHookPtr != IntPtr.Zero)
return;
hookProc = new HookProc(KeyboardhookProc); //键盘事件消息处理函数
nextHookPtr = SetWindowsHookEx((int)HookType.KeyboardLL,
hookProc,
Marshal.GetHINSTANCE(
Assembly.GetExecutingAssembly().GetModules()[0]),
0);
}
public void UnKeyboardHook()
{
if (nextHookPtr != IntPtr.Zero)
{
UnhookWindowsHookEx(nextHookPtr); //从Hook链中取消
nextHookPtr = IntPtr.Zero;
}
}
private IntPtr KeyboardhookProc(int code, IntPtr wparam, IntPtr lparam)
{
if (code >= 0)
{
KeyboardHookStruct myKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lparam, typeof(KeyboardHookStruct));
switch (wparam.ToInt32())
{
case WM_KEYDOWN:
Console.Write(string.Format("WM_KEYDOWN:{0}", Convert.ToChar(myKeyboardHookStruct.vkCode)));
break;
case WM_KEYUP:
Console.Write(string.Format("WM_KEYUP:{0:0}", Convert.ToChar(myKeyboardHookStruct.vkCode)));
break;
default:
break;
}
}
return CallNextHookEx(nextHookPtr, code, wparam, lparam); //返回,让后面的程序处理该消息
}
}
}
2 创建一个winform程序,测试上面的dll。
代码
//声明
private KeyboardHook keyhook = new KeyboardHook();
private void Form1_Load(object sender, EventArgs e)
{
//设置hook
keyhook.SetKeyboardHook();
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
//关闭hook
keyhook.UnKeyboardHook();
}
编译运行,在vs的output窗口中可以看到hook程序截获的键盘消息。