钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。
运行机制
1、钩子链表和钩子子程:
每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。这个列表的指针指向指定的,应用程 序定义的,被Hook子程调用的回调函数,也就是该钩子的各个处理子程。当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程。 一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。最近安装的钩子放在链的开始, 而最早安装的钩子放在最后,也就是后加入的先获得控制权。
Windows 并不要求钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Hook链表。如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。
钩子子程是一个应用程序定义的回调函数(CALLBACK Function),不能定义成某个类的成员函数,只能定义为普通的C函数。用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。
KeyboardHook.cs 类
public class KeyboardHook
{
private const int WH_KEYBOARD_LL = 13; //键盘
//键盘处理事件委托 ,当捕获键盘输入时调用定义该委托的方法.
private delegate int HookHandle(int nCode, int wParam, IntPtr lParam);
//客户端键盘处理事件
public delegate void ProcessKeyHandle(HookStruct param, out bool handle);
//接收SetWindowsHookEx返回值
private static int _hHookValue = 0;
//勾子程序处理事件
private HookHandle _KeyBoardHookProcedure;
//Hook结构
[StructLayout(LayoutKind.Sequential)]
public class HookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
//设置钩子
[DllImport("user32.dll")]
private static extern int SetWindowsHookEx(int idHook, HookHandle lpfn, IntPtr hInstance, int threadId);
//取消钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);
//调用下一个钩子
[DllImport("user32.dll")]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
//获取当前线程ID
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
//Gets the main module for the associated process.
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string name);
private IntPtr _hookWindowPtr = IntPtr.Zero;
//构造器
public KeyboardHook() { }
//外部调用的键盘处理事件
private static ProcessKeyHandle _clientMethod = null;
/// <summary>
/// 安装勾子
/// </summary>
/// <param name="hookProcess">外部调用的键盘处理事件</param>
public void InstallHook(ProcessKeyHandle clientMethod)
{
_clientMethod = clientMethod;
// 安装键盘钩子
if (_hHookValue == 0)
{
_KeyBoardHookProcedure = new HookHandle(OnHookProc);
_hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
_hHookValue = SetWindowsHookEx(
WH_KEYBOARD_LL,
_KeyBoardHookProcedure,
_hookWindowPtr,
0);
//如果设置钩子失败.
if (_hHookValue == 0) UninstallHook();
}
}
//取消钩子事件
public void UninstallHook()
{
if (_hHookValue != 0)
{
bool ret = UnhookWindowsHookEx(_hHookValue);
if (ret) _hHookValue = 0;
}
}
//钩子事件内部调用,调用_clientMethod方法转发到客户端应用。
private static int OnHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
//转换结构
HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));
if (_clientMethod != null)
{
bool handle = false;
//调用客户提供的事件处理程序。
_clientMethod(hookStruct, out handle);
if (handle) return 1; //1:表示拦截键盘,return 退出
}
}
return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
}
}
Form窗体
-
public partial class Form1 : Form
-
{
-
//勾子管理类
-
private KeyboardHookLib _keyboardHook = null;
-
public frmKeyboardHook()
-
{
-
InitializeComponent();
-
}文章来源:https://www.toymoban.com/news/detail-788069.html
-
private void button1_Click(object sender, EventArgs e)
-
{
-
//安装勾子
-
_keyboardHook = new KeyboardHookLib();
-
_keyboardHook.InstallHook(this.OnKeyPress);
-
}
-
private void button2_Click(object sender, EventArgs e)
-
{
-
//取消勾子
-
if (_keyboardHook != null) _keyboardHook.UninstallHook();
-
}
-
/// <summary>
-
/// 客户端键盘捕捉事件.
-
/// </summary>
-
/// <param name="hookStruct">由Hook程序发送的按键信息</param>
-
/// <param name="handle">是否拦截</param>
-
public void OnKeyPress(KeyboardHookLib.HookStruct hookStruct, out bool handle)
-
{
-
handle = false; //预设不拦截任何键
-
if (hookStruct.vkCode == 91) // 截获左win(开始菜单键)
-
{
-
handle = true;
-
}
-
if (hookStruct.vkCode == 92)// 截获右win
-
{
-
handle = true;
-
}
-
//截获Ctrl+Esc
-
if (hookStruct.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Control)
-
{
-
handle = true;
-
}
-
//截获alt+f4
-
if (hookStruct.vkCode == (int)Keys.F4 && (int)Control.ModifierKeys == (int)Keys.Alt)
-
{
-
handle = true;
-
}
-
//截获alt+tab
-
if (hookStruct.vkCode == (int)Keys.Tab && (int)Control.ModifierKeys == (int)Keys.Alt)
-
{
-
handle = true;
-
}
-
//截获F1
-
if (hookStruct.vkCode == (int)Keys.F1)
-
{
-
handle = true;
-
}
-
//截获Ctrl+Alt+Delete
-
if ((int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt + (int)Keys.Delete)
-
{
-
handle = true;
-
}
-
//如果键A~Z
-
if (hookStruct.vkCode >= (int)Keys.A && hookStruct.vkCode <= (int)Keys.Z)
-
{
-
//挡掉B键
-
if (hookStruct.vkCode == (int)Keys.B)
-
hookStruct.vkCode = (int)Keys.None; //设键为0
-
handle = true;
-
}
-
Keys key = (Keys)hookStruct.vkCode;
-
label1.Text = "你按下:" + (key == Keys.None ? "" : key.ToString());
-
}
-
}文章来源地址https://www.toymoban.com/news/detail-788069.html
到了这里,关于winform C#键盘钩子(Hook)拦截器,屏蔽键盘深入解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!