• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C#封装一个钩子类

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

利用C#设置钩子函数,并封装成类。如果想要实现全局钩子的话,必须将实现的代码封装到类库里。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
using System.Windows.Forms;

namespace PublicHook
{
    /// <summary>
    ///存放回调函数的委托
    /// </summary>
    public delegate int HOOKPROC(int nCode, IntPtr wParam, IntPtr lParam);
    public enum HookType
    {
        WH_KEYBOARD = 2,        //私有键盘钩子
        WH_EKYBOARD_LL = 13,    //全局键盘钩子
        WH_MOUSE = 7,           //私有鼠标钩子
        WH_MOUSE_LL = 14        //全局鼠标钩子
    }

    public abstract class hook
    {
        //设置钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(HookType idHook, HOOKPROC lpfn, IntPtr hInstance, int threadId);
        //取下钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(int idHook);
        //获取当前线程一个唯一的线程标识符
        [DllImport("kernel32")]
        public static extern int GetCurrentThreadId();
        //传递消息给下一个钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
        //获取一个应用程序或动态链接库的模块句柄
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);

        /// <summary>
        /// 钩子处理委托
        /// </summary>
        public HOOKPROC proc;
        /// <summary>
        /// 钩子类型
        /// </summary>
        public HookType type;
        /// <summary>
        /// 钩子的句柄
        /// </summary>
        public int hHook = 0;

        public hook(HOOKPROC proc, HookType type)
        {
            this.proc = proc;
            this.type = type;
        }
        //设置回调函数
        public void SetProc(HOOKPROC proc)
        {
            this.proc = proc;
        }

        public abstract int SetWindowsHookEx();
        public virtual void UnhookWindowsHookEx()
        {
            bool retKeyboard = true;
            //当前钩子句柄不为空,卸载钩子
            if (hHook != 0)
            {
                retKeyboard = UnhookWindowsHookEx(hHook);
                hHook = 0;
            }
            if (!retKeyboard)
                throw new Exception("UnhookWindowsHookEx failed.");
        }
    }

    public class PublicKBHook : hook
    {
        public PublicKBHook(HOOKPROC proc)
            : base(proc, HookType.WH_EKYBOARD_LL)
        { }
       
        public override int SetWindowsHookEx()
        {
            if (hHook == 0)
                hHook = SetWindowsHookEx(this.type, this.proc,
                    GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
            return hHook;
        }

        //Hook结构
        [StructLayout(LayoutKind.Sequential)]
        public class HookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
        /// <summary>
        ///回调函数,屏蔽除了回车和tab之外的所有键盘消息
        /// </summary>
        public int MyKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if ( nCode >= 0 )                  
            {
                HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure((IntPtr)lParam, typeof(HookStruct));
                //如果按下了回车,则将消息传给下一个钩子
                if ((Keys)hookStruct.vkCode == Keys.Enter ||
                    (Keys)hookStruct.vkCode == Keys.Tab)
                    return CallNextHookEx(hHook, nCode, wParam, lParam);
                //后门
                if ((Keys)hookStruct.vkCode == Keys.F1)
                    UnhookWindowsHookEx( hHook );
            }

            return 1;
        }
    }

    public class PrivateKBHook : hook
    {
        public PrivateKBHook(HOOKPROC proc)
            : base(proc, HookType.WH_KEYBOARD)
        { }

        public override int SetWindowsHookEx()
        {
            if (hHook == 0)
                hHook = SetWindowsHookEx(this.type, this.proc, IntPtr.Zero, GetCurrentThreadId());
            return hHook;
        }
    }

    public class PublicMouseHook : hook
    {
        public PublicMouseHook(HOOKPROC proc)
            : base(proc, HookType.WH_MOUSE_LL)
        { }

        public override int SetWindowsHookEx()
        {
            if (hHook == 0)
                hHook = SetWindowsHookEx(this.type, this.proc,
                    GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
            return hHook;
        }

        /// <summary>
        /// 屏蔽除了鼠标移动之外的鼠标消息
        /// </summary>
        public int MyMouseProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            //当wParam = 0x0200 时,进行鼠标移动操作
            //直接将消息传递给下一个钩子
            if (wParam == (IntPtr)0x0200)
                return CallNextHookEx(hHook, nCode, wParam, lParam);

            return 1;
        }
    }

    public class PrivateMouseHook : hook
    {
        public PrivateMouseHook(HOOKPROC proc)
            : base(proc, HookType.WH_MOUSE)
        { }

        public override int SetWindowsHookEx()
        {
            if (hHook == 0)
                hHook = SetWindowsHookEx(this.type, this.proc, IntPtr.Zero, GetCurrentThreadId());

            return hHook;
        }
    }
}

调用代码:

            //钩子句柄
            int hKBHook = 0, hMouseHook = 0;
            //设置全局键盘钩子
            PublicKBHook myKBHook = new PublicKBHook(null);
            myKBHook.SetProc(myKBHook.MyKeyboardProc);
            hKBHook = myKBHook.SetWindowsHookEx();      

卸载钩子:

//撤销钩子
                myKBHook.UnhookWindowsHookEx();

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#DataGridview用NPOI导出Excel文件发布时间:2022-07-10
下一篇:
C#判断点是否在直线上发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap