C#利用HOOK注册全局热键

C#利用HOOK注册全局热键的效果大家应该都见过,比如QQ的截图功能,即使QQ处于后台运行状态,仍然能获取键盘输入内容。要知道,C#程序在失去焦点的情况下KeyDown等键盘事件是得不到消息的,利用全局HOOK钩子技术就能在程序运行情况下,即使失去焦点,或者后台仍然能获取用户键盘输入内容。

C#利用HOOK注册全局热键

C#利用HOOK注册全局热键

为了方便,清晰的看到HOOK的获取消息、拦截消息的能力,我这里分别使用两个标签lable来显示来自HOOK的消息与来自按钮button3的键盘消息。当按下HOOK不拦截消息时,标签1与标签2的内容是一样的,当按下HOOK拦截的消息时,按钮的KeyDown事件将接收不到来自用户的按键信息。

C#代码

KeyboardHookLib.cs键盘HOOK管理类:

 /// <summary>
/// 键盘Hook管理类
/// </summary>
public class KeyboardHookLib
{
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 KeyboardHookLib() { }
//外部调用的键盘处理事件
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);
}
}

在Form1_Load事件中注册安装HOOK或者在按钮点击事件中注册安装HOOK。

_keyboardHook = new KeyboardHookLib();
_keyboardHook.InstallHook(this.OnKeyPress);

注意声明全局变量

KeyboardHookLib _keyboardHook;

HOOK处理方法

 /// <summary>/// 客户端键盘捕捉事件./// </summary>/// <param name="hookStruct">由Hook程序发送的按键信息</param>/// <param name="handle">是否拦截</param>public void OnKeyPress(KeyboardHookLib.HookStruct hookStruct, out bool handle){//是否拦截这个键handle = false;Keys key = (Keys)hookStruct.vkCode;if (key.ToString() == "F8"){//拦截F8handle = true;}else if (key.ToString() == "F12"){//拦截F12handle = true;}label1.Text = "HOOK按下了:" + key;}

在按钮3的KeyDown事件中写下获取按键代码:

 label2.Text = "按下了:" + e.KeyCode;

在关闭窗口事件Form1_FormClosed或者按钮点击事件中卸载HOOK

 if (_keyboardHook != null) _keyboardHook.UninstallHook();

到此整个HOOK全局热键与KeyDown的效果程序完成,至于HOOK全局热键能干嘛,就要看大家怎么用了,心理阴暗的人就把它当做键盘记录器使用,偷偷记录别人的输入内容,截获各种密码隐私等。哈哈哈,别试了,杀软第一个杀的就是HOOK,当然这里没使用注入功能,一般不会被杀的,最后警告大家不要做危害他人计算机的事哟~

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/241333.html

(0)
上一篇 2022年4月7日 00:32
下一篇 2022年4月7日 00:32

相关推荐

发表回复

登录后才能评论