全局鍵盤鉤子

全局鍵盤鉤子 C#.NET2005

using System;

using System.Runtime.InteropServices;

using System.Reflection;

using System.Threading;

using System.Windows.Forms;

using System.Diagnostics;

using System.Collections.Generic;

namespace HookGlobal

{

    /// <summary>

    /// 這個類可以讓你得到一個在運行中程序的所有鍵盤事件

    /// 並且引發一個帶KeyEventArgs和MouseEventArgs參數的.NET事件以便你很容易使用這些信息

    /// </summary>

    /// <remarks>

    /// 修改:lihx

    /// 修改時間:04.11.8

    /// </remarks>

    public class KeyBordHook

    {

        private const int WM_KEYDOWN = 0x100;

        private const int WM_KEYUP = 0x101;

        private const int WM_SYSKEYDOWN = 0x104;

        private const int WM_SYSKEYUP = 0x105;

        //全局的事件

        public event KeyEventHandler OnKeyDownEvent;

        public event KeyEventHandler OnKeyUpEvent;

        public event KeyPressEventHandler OnKeyPressEvent;

        static int hKeyboardHook = 0; //鍵盤鉤子句柄

        //鼠標常量

        public const int WH_KEYBOARD_LL = 13; //keyboard hook constant

        HookProc KeyboardHookProcedure; //聲明鍵盤鉤子事件類型.

        //聲明鍵盤鉤子的封送結構類型

        [StructLayout(LayoutKind.Sequential)]

        public class KeyboardHookStruct

        {

            public int vkCode; //表示一個在1到254間的虛似鍵盤碼

            public int scanCode; //表示硬件掃描碼

            public int flags;

            public int time;

            public int dwExtraInfo;

        }

        //裝置鉤子的函數

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

        //卸下鉤子的函數

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

        public static extern bool UnhookWindowsHookEx(int idHook);

        //下一個鉤掛的函數

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

        public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);

        [DllImport("user32")]

        public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);

        [DllImport("user32")]

        public static extern int GetKeyboardState(byte[] pbKeyState);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto,

CallingConvention = CallingConvention.StdCall)]

        private static extern IntPtr GetModuleHandle(string lpModuleName);

        public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);

        //先前按下的鍵

        public List<Keys> preKeys = new List<Keys>();

        /// <summary>

        /// 墨認的構造函數構造當前類的實例並自動的運行起來.

        /// </summary>

        public KeyBordHook()

        {

            Start();

        }

        //析構函數.

        ~KeyBordHook()

        {

            Stop();

        }

        public void Start()

        {

            //安裝鍵盤鉤子

            if (hKeyboardHook == 0)

            {

                KeyboardHookProcedure = new HookProc(KeyboardHookProc);

                //hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);

                Process curProcess = Process.GetCurrentProcess();

                ProcessModule curModule = curProcess.MainModule;

                hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(curModule.ModuleName), 0);

                if (hKeyboardHook == 0)

                {

                    Stop();

                    throw new Exception("SetWindowsHookEx ist failed.");

                }

            }

        }

        public void Stop()

        {

            bool retKeyboard = true;

            if (hKeyboardHook != 0)

            {

                retKeyboard = UnhookWindowsHookEx(hKeyboardHook);

                hKeyboardHook = 0;

            }

            //如果卸下鉤子失敗

            if (!(retKeyboard)) throw new Exception("UnhookWindowsHookEx failed.");

        }

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

        {

            if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))

            {

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

                //當有OnKeyDownEvent 或 OnKeyPressEvent不爲null時,ctrl alt shift keyup時 preKeys

                //中的對應的鍵增加                  

                if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))

                {

                    Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;

                    if (IsCtrlAltShiftKeys(keyData) && preKeys.IndexOf(keyData) == -1)

                    {

                        preKeys.Add(keyData);

                    }

                }

                //引發OnKeyDownEvent

                if (OnKeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))

                {

                    Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;

                    KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));

                    OnKeyDownEvent(this, e);

                }

                //引發OnKeyPressEvent

                if (OnKeyPressEvent != null && wParam == WM_KEYDOWN)

                {

                    byte[] keyState = new byte[256];

                    GetKeyboardState(keyState);

                    byte[] inBuffer = new byte[2];

                    if (ToAscii(MyKeyboardHookStruct.vkCode,

                    MyKeyboardHookStruct.scanCode,

                    keyState,

                    inBuffer,

                    MyKeyboardHookStruct.flags) == 1)

                    {

                        KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]);

                        OnKeyPressEvent(this, e);

                    }

                }

                //當有OnKeyDownEvent 或 OnKeyPressEvent不爲null時,ctrl alt shift keyup時 preKeys

                //中的對應的鍵刪除

                if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))

                {

                    Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;

                    if (IsCtrlAltShiftKeys(keyData))

                    {

                        for (int i = preKeys.Count - 1; i >= 0; i--)

                        {

                            if (preKeys[i] == keyData)

                            {

                                preKeys.RemoveAt(i);

                            }

                        }

                    }

                }

                //引發OnKeyUpEvent

                if (OnKeyUpEvent != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))

                {

                    Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;

                    KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));

                    OnKeyUpEvent(this, e);

                }

            }

            return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);

        }

 

        private Keys GetDownKeys(Keys key)

        {

            Keys rtnKey = Keys.None;

            foreach (Keys keyTemp in preKeys)

            {

                switch (keyTemp)

                {

                    case Keys.LControlKey:

                    case Keys.RControlKey:

                        rtnKey = rtnKey | Keys.Control;

                        break;

                    case Keys.LMenu:

                    case Keys.RMenu:

                        rtnKey = rtnKey | Keys.Alt;

                        break;

                    case Keys.LShiftKey:

                    case Keys.RShiftKey:

                        rtnKey = rtnKey | Keys.Shift;

                        break;

                    default:

                        break;

                }

            }

            rtnKey = rtnKey | key;

            return rtnKey;

        }

        private Boolean IsCtrlAltShiftKeys(Keys key)

        {

            switch (key)

            {

                case Keys.LControlKey:

                case Keys.RControlKey:

                case Keys.LMenu:

                case Keys.RMenu:

                case Keys.LShiftKey:

                case Keys.RShiftKey:

                    return true;

                default:

                    return false;

            }

        }

    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章