`
汪洋00700
  • 浏览: 23045 次
  • 性别: Icon_minigender_1
  • 来自: 常德
社区版块
存档分类

C# 键盘钩子 适合新手

    博客分类:
  • C#
阅读更多

这几天在研究C#,为什么会想学C#呢,因为在玩游戏的时候,想一键导入秘籍,嘿嘿大笑,感觉会方便很多,比如“魔兽争霸3”,“罗马帝国3”,我原本是想用java做的,发现实现起来比较麻烦,因为java的本地编程能力不强,需要JNA来调用,所以没有用java,转而想用别的编程语言,后来想用QT,但QT配置起来也不怎么好,于是决定用C#,好了,言归正传,下面将贴上代码,会做详细的注释,主体是借鉴的别人的代码。

 

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

namespace test              
{
    class KeyboardHookLib
    {
        //钩子类型:键盘
        private const int WH_KEYBOARD_LL = 13;

        //自己创建窗口按键
        public const int WM_KEYDOWN = 0x100;

        //全局系统按键
        public const int WM_SYSKEYDOWN = 0x104;

        //键盘处理事件委托.
        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 static 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();


        //获取关联进程的主模块
        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string name);


        private IntPtr _hookWindowPtr = IntPtr.Zero;


        //构造器
        public KeyboardHookLib() { }


        //外部调用的键盘处理事件,如果需要调用自己窗口建立的函数,则需要这行代码
        //private static ProcessKeyHandle _clientMethod = null;

        /// 安装勾子
        //如果需要调用自己窗口建立的函数,则需要这行代码
        // public void InstallHook(ProcessKeyHandle clientMethod)   
        //{
        //如果需要调用自己窗口建立的函数,则需要这行代码
        //_clientMethod = clientMethod;        
        /*
         * _clientMethod 相当于一个发射的工具,
         * 从钩子代码这儿调用到你自己窗口建立的函数那儿
         * 我做的是个最简单的辅助,
         * 所以不需要调用到自己的函数那儿,
         * 所以就没有把创建它
          */
        public void InstallHook()
        {

            // 安装键盘钩子
            if (_hHookValue == 0)
            {
                //GetHookProc 是钩子内部调用的函数,当按下键盘时,
                //会调用到这儿来,可以改变名字
                _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;
            }
        }
        //钩子事件内部调用,调用_clientMethod方法转发到客户端应用。
        private static int GetHookProc(int nCode, int wParam, IntPtr lParam)
        {
            //当nCode大于0,并且是按下事件时为1
            if (nCode >= 0 && (wParam == WM_KEYDOWN) || (wParam == WM_SYSKEYDOWN))
            {
               
                //转换结构
    HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));

                //是否拦截按键的标识符,默认不拦截
                bool handle = false;

                switch ((Keys)hookStruct.vkCode)
                {
                     //将拦截标识符置为拦截,向当前窗口发送一个回车,
                    //再发送greenisgood 10000,再发送一个回车
                    case Keys.F1: handle = true; SendKeys.Send("{ENTER}"); SendKeys.Send("greenisgood 10000"); SendKeys.Send("{ENTER}"); break;
                }

                /*
                if (_clientMethod != null)
                {
                    //调用客户提供的事件处理程序。
                    //_clientMethod(hookStruct, out handle);
                    //if (handle) return 1; //1:表示拦截键盘,return 退出
                }
                 */
                if (handle) return 1;
            }
            return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
        }
    }
}

 钩子管理类就OK了,那么,就只要在你自己的窗口安装钩子即可,代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace test
{
    public partial class Form1 : Form
    {
       private KeyboardHookLib _keyboardHook = null;

        //当运行程序默认安装钩子,也可以建一个按钮,手动安装
        public Form1()
        {
            InitializeComponent();
            _keyboardHook = new KeyboardHookLib();
           //如果需要调用回来,安装钩子时把函数传过去
           // _keyboardHook.InstallHook(this.newKeyPress);
            _keyboardHook.InstallHook();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        // _clientMethod 便是调用到这个函数来
        //private void newKeyPress(KeyboardHookLib.HookStruct hookStruct, out bool handle)
        //{
            //handle = true;
            //Keys key = (Keys)hookStruct.vkCode;
            //richTextBox1.Text  += key.ToString();
       // }
        //窗口退出事件
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //卸载钩子
            if (_keyboardHook != null) _keyboardHook.UninstallHook();
        }

        //右键菜单-退出事件
        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //卸载钩子
            if (_keyboardHook != null) _keyboardHook.UninstallHook();
            Close();
        }

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

 

 

大功告成,最简单的钩子就OK了,暂时没有弄组合键,可以自己百度看一下,主体代码我也是百度的,自己研究明白了,才把代码贴在这儿的,大神勿喷,新手弄明白了点个赞,不明白的地方可以交流一下。吐舌头

 

 

  • 大小: 241.5 KB
分享到:
评论
1 楼 汪洋00700 2015-01-17  
    

相关推荐

Global site tag (gtag.js) - Google Analytics