C#:键盘钩子的使用,实现键盘屏蔽 及 全局改键功能

1.引入

由于需要使用动态链接库及Process进程类,所以需要在项目中引入命名空间

using System.Diagnostics;

using System.Runtime.InteropServices;   //调用操作系统动态链接库

 

2.键盘屏蔽

实现屏蔽键盘的功能,并且把按的任意的一个键的值显示在标签中。

如 按下了 space windows 等,不会产生键盘该有的功能,因为做了屏蔽处理,而是显示键值在标签上。

代码如下:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices; //调用操作系统动态链接库
using System.Windows.Forms;

namespace WindowsFormsApp14 {

    
    public partial class Form1 : Form {
        private KeyboardHookLib _keyboardHook = null;
        public Form1() {
            InitializeComponent();
        }

        //开启改键
        private void button1_Click(object sender, EventArgs e) {
//把客户端委托函数传给键盘钩子类KeyBoardHookLib
            _keyboardHook.InstallHook(this.Form1_KeyPress);

        }

        //退出改键
        private void button2_Click(object sender, EventArgs e) {
            if (_keyboardHook != null) {
                _keyboardHook.UninstallHook();
            }
        }

        private void Form1_Load(object sender, EventArgs e) {

        }
        
        //窗口退出事件
        private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
            if (_keyboardHook != null) {
                //卸载钩子
                _keyboardHook.UninstallHook();
            }
        }
        

        //右键菜单-与此例无关
        private void Form1_MouseDoubleClick(object sender, MouseEventArgs e) {
            if (WindowState == FormWindowState.Minimized) {
                //还原窗体显示
                WindowState = FormWindowState.Normal;
                //激活窗体并给予它焦点
                this.Activate();
            }
        }

        //客户端传递的委托函数
        private void Form1_KeyPress(KeyboardHookLib.HookStruct hookStruct, out bool handle) {
            handle = false; //预设不拦截
            Keys key = (Keys)hookStruct.vkVode;
            String keyname = key.ToString();
            this.showresult.Text = keyname;
            return;
        }
    }

/
    class KeyboardHookLib {
        //钩子类型:键盘
        private const int WH_KEYBOARD_LL = 13; //全局钩子键盘为13,线程钩子键盘为2
        private const int WM_KEYDOWN = 0x0100; //键按下
        private const int WM_KEYUP = 0x0101; //键弹起
        //全局系统按键
        private const int WM_SYSKEYDOWN = 0x104;
        //键盘处理委托事件,捕获键盘输入,调用委托方法
        private delegate int HookHandle(int nCode, int wParam, IntPtr lParam);
        private static HookHandle _keyBoardHookProcedure;
        //客户端键盘处理委托事件
        public delegate void ProcessKeyHandle(HookStruct param, out bool handle);
        private static ProcessKeyHandle _clientMethod = null;
        //接收SetWindowsHookEx返回值   判断是否安装钩子
        private static int _hHookValue = 0;
        //Hook结构 存储按键信息的结构体
        [StructLayout(LayoutKind.Sequential)]
        public class HookStruct {
            public int vkVode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
        
        //安装钩子
        //idHook为13代表键盘钩子为14代表鼠标钩子,lpfn为函数指针,指向需要执行的函数,hIntance为指向进程快的指针,threadId默认为0就可以了
        [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)]
        public static extern bool UnhookWindowsHookEx(int idHook);
        //调用下一个钩子
        [DllImport("user32.dll")]
        public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
        //获取当前线程id
        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();
        //通过线程Id,获取进程快
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(String name);

        private IntPtr _hookWindowPtr = IntPtr.Zero;

        public KeyboardHookLib() { }

        #region
        //加上客户端方法的委托的安装钩子
        public void InstallHook(ProcessKeyHandle clientMethod) {
            //客户端委托事件 
            _clientMethod = clientMethod;
            //安装键盘钩子
            if (_hHookValue == 0) {
                _keyBoardHookProcedure = new HookHandle(GetHookProc);
                _hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
                _hHookValue = SetWindowsHookEx(
                    WH_KEYBOARD_LL,
                    _keyBoardHookProcedure,
                    _hookWindowPtr,
                    0
                    );
                if (_hHookValue == 0) {
                    //设置钩子失败
                    UninstallHook();
                }
            }
        }
        #endregion


        //取消钩子事件
        public void UninstallHook() {
            if (_hHookValue != 0) {
                bool ret = UnhookWindowsHookEx(_hHookValue);
                if (ret) {
                    _hHookValue = 0;
                }
            }
        }

        private static int GetHookProc(int nCode, int wParam, IntPtr lParam) {
            //当nCode大于0,并且时按下事件时为1
            if (nCode >= 0 && (wParam == WM_KEYDOWN) || (wParam == WM_KEYDOWN)) {
                //将按键信息转换为结构体
                HookStruct hookStruc = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));
                //是否拦截按键的标识符,默认不拦截
                bool handle = false;
                        //客户端调用  
                        _clientMethod(hookStruc,out handle); //如果传递了客户端委托,就调用
                        handle = true; //如果这个handle为false,则代表不拦截此次按键,按了 windows等键会执行客户端键值显示,但是同时也会产生该键本有的功能。

                if (handle){ return 1; }
            }
            return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
        }

    }




}

 

3.全局改键

这个案例是把键盘的UP键改成了 回车键加greendisgood 1000多个字符键再加一个回车键,玩过魔兽的都知道这是魔兽秘籍。

using System;
using System.Diagnostics;
using System.Runtime.InteropServices; //调用操作系统动态链接库
using System.Windows.Forms;

namespace WindowsFormsApp14 {

    
    public partial class Form1 : Form {
        private KeyboardHookLib _keyboardHook = null;
        public Form1() {
            InitializeComponent();
        }

        //开启改键
        private void button1_Click(object sender, EventArgs e) {
            _keyboardHook = new KeyboardHookLib();
            _keyboardHook.InstallHook();

        }

        //退出改键
        private void button2_Click(object sender, EventArgs e) {
            if (_keyboardHook != null) {
                _keyboardHook.UninstallHook();
            }
        }

        private void Form1_Load(object sender, EventArgs e) {

        }
        
        //窗口退出事件
        private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
            if (_keyboardHook != null) {
                //卸载钩子
                _keyboardHook.UninstallHook();
            }
        }
        

        //右键菜单
        private void Form1_MouseDoubleClick(object sender, MouseEventArgs e) {
            if (WindowState == FormWindowState.Minimized) {
                //还原窗体显示
                WindowState = FormWindowState.Normal;
                //激活窗体并给予它焦点
                this.Activate();
            }
        }

    }

    class KeyboardHookLib {
        //钩子类型:键盘
        private const int WH_KEYBOARD_LL = 13; //全局钩子键盘为13,线程钩子键盘为2
        private const int WM_KEYDOWN = 0x0100; //键按下
        private const int WM_KEYUP = 0x0101; //键弹起
        //全局系统按键
        private const int WM_SYSKEYDOWN = 0x104;
        //键盘处理委托事件,捕获键盘输入,调用委托方法
        private delegate int HookHandle(int nCode, int wParam, IntPtr lParam);
        private static HookHandle _keyBoardHookProcedure;
        //接收SetWindowsHookEx返回值   
        private static int _hHookValue = 0;
        //Hook结构 存储按键信息的结构体
        [StructLayout(LayoutKind.Sequential)]
        public class HookStruct {
            public int vkVode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
        
        //安装钩子
        //idHook为13代表键盘钩子为14代表鼠标钩子,lpfn为函数指针,指向需要执行的函数,hIntance为指向进程快的指针,threadId默认为0就可以了
        [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)]
        public static extern bool UnhookWindowsHookEx(int idHook);
        //调用下一个钩子
        [DllImport("user32.dll")]
        public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
        //获取当前线程id
        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();
        //通过线程Id,获取进程快
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(String name);

        private IntPtr _hookWindowPtr = IntPtr.Zero;

        public KeyboardHookLib() { }

        public void InstallHook() {
            //安装键盘勾子
            if (_hHookValue == 0) {
                _keyBoardHookProcedure = new HookHandle(GetHookProc);
                //得到进程块
                _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;
                }
            }
        }

        private static int GetHookProc(int nCode, int wParam, IntPtr lParam) {
            //当nCode大于0,并且时按下事件时为1
            if (nCode >= 0 && (wParam == WM_KEYDOWN) || (wParam == WM_KEYDOWN)) {
                //将按键信息转换为结构体
                HookStruct hookStruc = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));
                //是否拦截按键的标识符,默认不拦截
                bool handle = false;
                switch ((Keys)hookStruc.vkVode) {
                    //将拦截标识符置为拦截,如果按了上键相当于向当前窗口发送一个回车
                    //再发送greendisgood 10000,再发送一个回车
                    case Keys.Up:
                        handle = true;
                        SendKeys.Send("{ENTER}");
                        SendKeys.Send("greendisgood 1000");
                        SendKeys.Send("{ENTER}");
                        break;
                }
                //1表示拦截键盘
                if (handle){ return 1; }
            }
            return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
        }

    }









}

先运行程序,然后点击开启改键,然后缩小程序,然后随便打开一个可以输入文字的东西如文档等,我这里直接拿一个记事本做测试,文档一开始为空,然后按一下UP上键,内容如下:

有输入法的话,先把输入法关了,不然会乱码!

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值