蓝天旭日

高手如云,自己只是个菜鸟而已! 没有人在意你曾经的努力和散漫,只有人关注你是否有成就......
posts - 19, comments - 105, trackbacks - 0, articles - 6
  博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

C#钩子实现简单鼠标键盘的监控和屏蔽

Posted on 2008-01-14 15:40 蓝天旭日 阅读(...) 评论(...) 编辑 收藏
    

概要

1 目的:完成简单的监控和屏蔽

2 技术:钩子(系统监控必须全局钩子)

3 步骤:

   A 安装钩子

   B 回调函数

   C 处理函数

   D 普通业务处理

   ……

4 完成

下载源程序和运行程序

http://www.cnblogs.com/Files/hocylan/KeyboardHook.rar

运行界面如下:

说明:

C++中实现该功能十分简单,也有很多经典例子可以实现,在C#中确有很多问题会出现。

对于钩子知识不太熟悉可以参考我转载的另一篇文章:http://www.cnblogs.com/hocylan/articles/1033895.html[微软HOOK技术专题]

大概步骤

其实主要就是调用windows API
第一步
:安装钩子:SetWindowsHookEx(WH_Codes idHook, HookProc lpfn,IntPtr pInstance, int threadId);

第二步:回调和处理 CallNextHookEx(IntPtr pHookHandle, int nCode,Int32 wParam, IntPtr lParam);

第三步:完成普通的业务处理其它流程

        将封装的钩子应用到系统中…….

        private void start_Click(object sender, EventArgs e)

        { hook_Main.InstallHook("1");}

        private void stop_Click(object sender, EventArgs e)

        {this.hook_Main.UnInstallHook();}

        private void stopkeyboard_Click(object sender, EventArgs e)

        { hook_Main.InstallHook("2"); }

第四步:拆卸钩子UnhookWindowsHookEx(IntPtr pHookHandle);

 

四 重要代码和解释:

*封装的hook类:

using System;

using System.Windows.Forms;

using System.Runtime.InteropServices; //必须引用

using System.Reflection; //必须引用

namespace KeyboardHook

{

    class Hocy_Hook

    {

        #region私有常量

         ///<summary>

         ///按键状态数组

         ///</summary>

         private readonly byte[] m_KeyState = new byte[ 256 ];

        private string flags;

        //flag=0 正常 flag=1 监控状态 flag=2 屏蔽键盘//

         #endregion私有常量

         #region私有变量

         ///<summary>

         ///鼠标钩子句柄

         ///</summary>

         private IntPtr m_pMouseHook = IntPtr.Zero;

         ///<summary>

         ///键盘钩子句柄

         ///</summary>

         private IntPtr m_pKeyboardHook = IntPtr.Zero;

         ///<summary>

         ///鼠标钩子委托实例

         ///</summary>

         ///<remarks>

         ///不要试图省略此变量,否则将会导致

         ///激活CallbackOnCollectedDelegate 托管调试助手(MDA)。

         ///详细请参见MSDN中关于CallbackOnCollectedDelegate 的描述

         ///</remarks>

         private HookProc m_MouseHookProcedure;

         ///<summary>

         ///键盘钩子委托实例

         ///</summary>

         ///<remarks>

         ///不要试图省略此变量,否则将会导致

         ///激活CallbackOnCollectedDelegate 托管调试助手(MDA)。

         ///详细请参见MSDN中关于CallbackOnCollectedDelegate 的描述

         ///</remarks>

         private HookProc m_KeyboardHookProcedure;

        // 添加

        public event MouseEventHandler OnMouseActivity;

        private const byte VK_SHIFT = 0x10 ;

        private const byte VK_CAPITAL = 0x14;

        private const byte VK_NUMLOCK = 0x90;

         #endregion私有变量

         #region事件定义

         ///<summary>

         ///鼠标更新事件

         ///</summary>

         ///<remarks>当鼠标移动或者滚轮滚动时触发</remarks>

         public event MouseUpdateEventHandler OnMouseUpdate;

         ///<summary>

         ///按键按下事件

         ///</summary>

         public event KeyEventHandler OnKeyDown;

         ///<summary>

         ///按键按下并释放事件

         ///</summary>

         public event KeyPressEventHandler OnKeyPress;

         ///<summary>

         ///按键释放事件

         ///</summary>

         public event KeyEventHandler OnKeyUp;

         #endregion事件定义

         #region私有方法

         ///<summary>

         ///鼠标钩子处理函数

         ///</summary>

         ///<param name="nCode"></param>

         ///<param name="wParam"></param>

         ///<param name="lParam"></param>

         ///<returns>鼠标钩子处理函数</returns>

         private int MouseHookProc( int nCode, Int32 wParam, IntPtr lParam )

         {

 if ((nCode >= 0) && (OnMouseActivity != null))

            {

                //Marshall the data from callback.

                MouseHookStruct mouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));

                //detect button clicked

                MouseButtons button = MouseButtons.None;

                short mouseDelta = 0;

                switch (wParam)

                {

                    case (int)WM_MOUSE.WM_LBUTTONDOWN:

                        //case WM_LBUTTONUP:

                        //case WM_LBUTTONDBLCLK:

                        button = MouseButtons.Left;

                        break;

                    case (int)WM_MOUSE.WM_RBUTTONDOWN:

                        //case WM_RBUTTONUP:

                        //case WM_RBUTTONDBLCLK:

                        button = MouseButtons.Right;

                        break;

                    case (int)WM_MOUSE.WM_MOUSEWHEEL:

                        //If the message is WM_MOUSEWHEEL, the high-order word of mouseData member is the wheel delta.

                        //One wheel click is defined as WHEEL_DELTA, which is 120.

                        //(value >> 16) & 0xffff; retrieves the high-order word from the given 32-bit value

                        mouseDelta = (short)((mouseHookStruct.MouseData>> 16) & 0xffff);

                        //TODO: X BUTTONS (I havent them so was unable to test)

                        //If the message is WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP,

                        //or WM_NCXBUTTONDBLCLK, the high-order word specifies which X button was pressed or released,

                        //and the low-order word is reserved. This value can be one or more of the following values.

                        //Otherwise, mouseData is not used.

                        break;

                }

                //double clicks

                int clickCount = 0;

                if (button != MouseButtons.None)

                    if (wParam == (int)WM_MOUSE.WM_LBUTTONDBLCLK || wParam == (int)WM_MOUSE.WM_RBUTTONDBLCLK) clickCount = 2;

                    else clickCount = 1;

                //generate event

                MouseEventArgs e = new MouseEventArgs(

                                                   button,

                                                   clickCount,

                                                   mouseHookStruct.Point.X,

                                                   mouseHookStruct.Point.Y,

                                                   mouseDelta);

                //raise it

                OnMouseActivity(this, e);

            } 

           

            //*

              return Win32API.CallNextHookEx( this.m_pMouseHook, nCode, wParam, lParam );

         }

         ///<summary>

         ///键盘钩子处理函数

         ///</summary>

         ///<param name="nCode"></param>

         ///<param name="wParam"></param>

         ///<param name="lParam"></param>

         ///<returns></returns>

         ///<remarks></remarks>

         private int KeyboardHookProc( int nCode, Int32 wParam, IntPtr lParam )

         {

          

            switch (flags)

            {

                case "2":

                    return 1;

                    break;

                case "1":

                    break;

            }

            bool handled = false;

            //it was ok and someone listens to events

            if ((nCode >= 0) && (this.OnKeyDown != null || this.OnKeyUp!= null || this.OnKeyPress!= null))

            {

                //read structure KeyboardHookStruct at lParam

                KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));

                //raise KeyDown

                if (this.OnKeyDown != null && (wParam == (int)WM_KEYBOARD.WM_KEYDOWN || wParam == (int)WM_KEYBOARD.WM_SYSKEYDOWN))

                {

                    Keys keyData = (Keys)MyKeyboardHookStruct.VKCode;

                    KeyEventArgs e = new KeyEventArgs(keyData);

                   this.OnKeyDown(this, e);

                    handled = handled || e.Handled;

                }

                // raise KeyPress

                    if (this.OnKeyPress != null && wParam == (int)WM_KEYBOARD.WM_KEYDOWN)

                    {

                        bool isDownShift, isDownCapslock;

                        try

                        {

                             isDownShift = ((Win32API.GetKeyStates(VK_SHIFT) & 0x80) == 0x80 ? true : false);

                            isDownCapslock = (Win32API.GetKeyStates(VK_CAPITAL) != 0 ? true : false);

                        }

                        catch

                        {

                            isDownCapslock = false;

                            isDownShift= false;

                        }

                        byte[] keyState = new byte[256];

                       Win32API.GetKeyboardState(keyState);

                        byte[] inBuffer = new byte[2];

                        if (Win32API.ToAscii(MyKeyboardHookStruct.VKCode,

                                  MyKeyboardHookStruct.ScanCode,

                                  keyState,

                                  inBuffer,

                                  MyKeyboardHookStruct.Flags) == 1)

                        {

                            char key = (char)inBuffer[0];

                            if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key)) key = Char.ToUpper(key);

                            KeyPressEventArgs e = new KeyPressEventArgs(key);

                            this.OnKeyPress(this, e);

                            handled = handled || e.Handled;

                        }

                    }

                // raise KeyUp

                if (this.OnKeyUp != null && (wParam == (int)WM_KEYBOARD.WM_KEYUP || wParam == (int)WM_KEYBOARD.WM_SYSKEYUP))

                {

                    Keys keyData = (Keys)MyKeyboardHookStruct.VKCode;

                    KeyEventArgs e = new KeyEventArgs(keyData);

                    this.OnKeyUp(this, e);

                    handled = handled || e.Handled;

                }

            }

            //if event handled in application do not handoff to other listeners

            if (handled)

                return 1;

            else

                return Win32API.CallNextHookEx(this.m_pKeyboardHook, nCode, wParam, lParam);

        }

            

         #endregion私有方法

         #region公共方法

         ///<summary>

         ///安装钩子

         ///</summary>

         ///<returns></returns>

         public bool InstallHook(string flagsinfo)

         {

            this.flags = flagsinfo;

IntPtr pInstance = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().ManifestModule);

//pInstance = (IntPtr)4194304;

          //注意:很多时候得到的pInstanc无法安装钩子,请检查值是否为4194304,在应用程序中可以直接取得pinstance的

           // IntPtr pInstanc2 = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly());

           // Assembly.GetExecutingAssembly().GetModules()[0]

              //安装鼠标钩子

              if ( this.m_pMouseHook == IntPtr.Zero )

              {

                   this.m_MouseHookProcedure = new HookProc( this.MouseHookProc );

                   this.m_pMouseHook = Win32API.SetWindowsHookEx( WH_Codes.WH_MOUSE_LL,this.m_MouseHookProcedure, pInstance, 0 );

// WH_Codes.WH_MOUSE_LL为全局钩子即系统钩子,否则应该为WH_Codes.WH_KEYBOARD,即普通钩子

                   if ( this.m_pMouseHook == IntPtr.Zero )

                   {

                       this.UnInstallHook();

                       return false;

                   }

              }

              if ( this.m_pKeyboardHook == IntPtr.Zero ) //安装键盘钩子

              {

                   this.m_KeyboardHookProcedure = new HookProc( this.KeyboardHookProc );

                  // WH_Codes.WH_KEYBOARD_LL为全局钩子即系统钩子,否则应该为WH_Codes.WH_KEYBOARD,即普通钩子

                   this.m_pKeyboardHook = Win32API.SetWindowsHookEx( WH_Codes.WH_KEYBOARD_LL,this.m_KeyboardHookProcedure, pInstance, 0 );

                   if ( this.m_pKeyboardHook == IntPtr.Zero )

                   {

                       this.UnInstallHook();

                       return false;

                   }

              }

              return true;

         }

         ///<summary>

         ///卸载钩子

         ///</summary>

         ///<returns></returns>

         public bool UnInstallHook()

         {

              bool result = true;

              if ( this.m_pMouseHook != IntPtr.Zero )

              {

                   result = ( Win32API.UnhookWindowsHookEx( this.m_pMouseHook ) && result );

                   this.m_pMouseHook = IntPtr.Zero;

              }

              if ( this.m_pKeyboardHook != IntPtr.Zero )

              {

                   result = ( Win32API.UnhookWindowsHookEx( this.m_pKeyboardHook ) && result );

                   this.m_pKeyboardHook = IntPtr.Zero;

              }

              return result;

         }

         #endregion公共方法

         #region构造函数

         ///<summary>

         ///钩子类

         ///</summary>

         ///<remarks>本类仅仅简单实现了WH_KEYBOARD_LL 以及WH_MOUSE_LL </remarks>

         public Hocy_Hook()

         {

              Win32API.GetKeyboardState( this.m_KeyState );

         }

         #endregion构造函数

    }

}

另外感谢来自GermanyGeorge Mamaladze,看了他的代码,给了我比较好的思路

http://www.codeproject.com/KB/cs/globalhook.aspx