keyborad hook

关于原理请参考我的另一篇文章 mouse Hook.

新建类:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace TestHook
{
    class KeyboardHook
    {
        int hHook;
        public bool IsHooking = false;
 
        Win32Api.HookProc KeyboardHookDelegate;
        public event KeyEventHandler OnKeyDownEvent;

        public event KeyEventHandler OnKeyUpEvent;

        public event KeyPressEventHandler OnKeyPressEvent;
 
        //Store the control key is pressed, the key used to generate specific
        private List<Keys> preKeysList = new List<Keys>();

        public KeyboardHook() { }
 
        ~KeyboardHook()
        {
            if (IsHooking)
            {
                Win32Api.UnhookWindowsHookEx(hHook);
            }
        }
 
        public void UnHook()
        {
            if (IsHooking)
            {
                if (Win32Api.UnhookWindowsHookEx(hHook))
                {
                    IsHooking = false;
                }
            }
        }
 
        public bool SetHook()
        {

            KeyboardHookDelegate = new Win32Api.HookProc(KeyboardHookProc);

            Process cProcess = Process.GetCurrentProcess();

            ProcessModule cModule = cProcess.MainModule;

            var mh = Win32Api.GetModuleHandle(cModule.ModuleName);

            hHook = Win32Api.SetWindowsHookEx(Win32Api.WH_KEYBOARD_LL, KeyboardHookDelegate, mh, 0);

            if (hHook == 0)
                return false;

            IsHooking = true;

            return true;
        }
 
 
     
 
        private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
        {

            //If the message was discarded (nCode<0) or if no event handler is not triggered event
            if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))
            {

                Win32Api.KeyboardHookStruct KeyDataFromHook = (Win32Api.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.KeyboardHookStruct));

                Keys keyData = (Keys)KeyDataFromHook.vkCode;

                //Control keypressed

                //Get key value
                int acctualValue = -1;

                byte[] keyState = new byte[256];

                Win32Api.GetKeyboardState(keyState);


                byte[] inBuffer = new byte[2];

                if (Win32Api.ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1)
                {
                    acctualValue = inBuffer[0];
                }

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

                    if (IsFounctionKeys(keyData) && preKeysList.IndexOf(keyData) == -1)
                    {

                        preKeysList.Add(keyData);
                    }

                }
 
                // WM_KEYDOWN and WM_SYSKEYDOWN message 
 
                if (OnKeyDownEvent != null && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN))
                {
                    KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));
 
                    Win32Api.ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags);

                    OnKeyDownEvent(acctualValue, e);
 
                }
 
 
                //WM_KEYDOWN message ,lead to OnKeyPressEvent  Remove this founction for now
                //If pressed key ,then record it 
                if (OnKeyPressEvent != null && wParam == Win32Api.WM_KEYDOWN)
                {

                    if (Win32Api.ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1)
                    {

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

                        OnKeyPressEvent(this, e);

                    }

                }

                //control keyup
                if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP))
                {

                    if (IsFounctionKeys(keyData))
                    {

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

                            if (preKeysList[i] == keyData) { preKeysList.RemoveAt(i); }

                        }

                    }

                }

                //WM_KEYUP and WM_SYSKEYUP message,lead to OnKeyUpEvent events
                if (OnKeyUpEvent != null && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP))
                {

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

                    OnKeyUpEvent(acctualValue, e);

                }

            }

            return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);

        }
 
        private Boolean IsFounctionKeys(Keys key)
        {

            if (key == Keys.LControlKey || key == Keys.RControlKey || key == Keys.LMenu || key == Keys.RMenu
                || key == Keys.LShiftKey || key == Keys.RShiftKey /* || key == Keys.LWin ||key == Keys.RWin*/)
            {
                return true;
            }

            return false;

        }
 
        //According to the control key has been pressed to generate key
 
        /// <summary>
        /// Juage the char is sprintable
        /// </summary>
        /// <returns></returns>
        private bool IsSprint(char input)
        {
            if (input > 0x1f && input != 0x7f)
            {
                return true;
            }
            return false;
        }

        private Keys GetDownKeys(Keys key)
        {

            Keys rtnKey = Keys.None;

            foreach (Keys i in preKeysList)
            {
                if (i == Keys.LControlKey || i == Keys.RControlKey) { rtnKey = rtnKey | Keys.Control; }

                if (i == Keys.LMenu || i == Keys.RMenu) { rtnKey = rtnKey | Keys.Alt; }

                if (i == Keys.LShiftKey || i == Keys.RShiftKey) { rtnKey = rtnKey | Keys.Shift; }
            }

            return rtnKey | key;

        }
    }
}
建类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
 
namespace TestHook
{
    class Win32Api
    {
        #region Normal Data Struct

        public const int WM_KEYDOWN = 0x100;

        public const int WM_KEYUP = 0x101;

        public const int WM_SYSKEYDOWN = 0x104;

        public const int WM_SYSKEYUP = 0x105;

        public const int WH_KEYBOARD_LL = 13;

        public const int WH_MOUSE_LL = 14;

        public const int WM_MOUSEMOVE = 0x200;

        public const int WM_LBUTTONDOWN = 0x201;

        public const int WM_RBUTTONDOWN = 0x204;

        public const int WM_MBUTTONDOWN = 0x207;

        public const int WM_LBUTTONUP = 0x202;

        public const int WM_RBUTTONUP = 0x205;

        public const int WM_MBUTTONUP = 0x208;

        public const int WM_LBUTTONDBLCLK = 0x203;

        public const int WM_RBUTTONDBLCLK = 0x206;

        public const int WM_MBUTTONDBLCLK = 0x209;

        //define keyboard meesage struct
        [StructLayout(LayoutKind.Sequential)]
        public class KeyboardHookStruct
        {
            //Represents a virtual keyboard codes between 1 and 254
            public int vkCode;
            //Indicate a hardware scan code
            public int scanCode;
 
            public int flags;

            public int time;

            public int dwExtraInfo;

        }

        //Declares a Point type is marshaled
        [StructLayout(LayoutKind.Sequential)]
        public class POINT
        {
            public int x;
            public int y;
        }

        //Declaring a mouse hook marshaled structure types
        [StructLayout(LayoutKind.Sequential)]
        public class MouseHookStruct
        {
            public POINT pt;
            public int hWnd;
            public int wHitTestCode;
            public int dwExtraInfo;
        }
        #endregion
 
        #region Api
 
        public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);

        //install hook 
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

        //uninstall hook
        [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)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
        #endregion
 
        #region Copied from Prism Management Studio Common
        [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();
        #endregion
 
        #region GetMessageExtraInfo
        [DllImport("user32.dll", EntryPoint = "GetMessageExtraInfo", SetLastError = true)]
        public static extern IntPtr GetMessageExtraInfo();
        #endregion
 
        #region MapVirtualKey
        [DllImport("user32.dll")]
        public static extern UInt32 MapVirtualKey(UInt32 uCode, UInt32 uMapType);
        #endregion
    }
}
最后在winform里面注册事件并设置钩子。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace TestHook
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;//不检查线程之间的冲突
        }
        TestKeyBorddelegate keyBoardDelegate;
        KeyboardHook keyboardHook = new KeyboardHook();
 
        private void btnStartKeyBoard_Click(object sender, EventArgs e)
        {         
            keyboardHook.OnKeyDownEvent += KeyDown;//注册响应方法
            if (!keyboardHook.SetHook())//设置不成功
            {
                keyboardHook.OnKeyDownEvent -= KeyDown;
            }
        }
 
        //方法,键盘按下的方法
        private void KeyDown(object sender, KeyEventArgs e)
        {
            keyBoardDelegate = (s) => { this.Text = s; };
            keyBoardDelegate.BeginInvoke(e.KeyValue.ToString(),null,null);//开辟新线程否则可能造成form的卡顿。
        }
 
        private void btnCancel_Click(object sender, EventArgs e)
        {
            keyboardHook.OnKeyDownEvent -= KeyDown;
            keyboardHook.UnHook();
        }
    }
    public delegate void TestKeyBorddelegate(string s);
 
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值