`

如何在C#中使用全局鼠标、键盘Hook

    博客分类:
  • C#
阅读更多
今天,有个同事问我,怎样在C#中使用全局钩子?以前写的全局钩子都是用unmanaged C或C++写个DLL来实现,可大家都知道,C#是基于.Net Framework的,是managed,怎么实现全局钩子呢?于是开始到网上搜索,好不容易找到一篇,318804 - HOW TO: Set a Windows Hook in Visual C# .NET,里面详细的说明了如何使用鼠标钩子捕获鼠标的移动等,可是,它只能在Application里起作用,出了Application就没用了,就是说它还是没有实现全局钩子,而且文章结尾处说:“Global Hooks are not supported in the .NET Framework...”,这可怎么办呢?

  别担心,办法总是有的,经过一番摸索以后,发现WH_KEYBORAD_LL和WH_MOUSE_LL这两个low-level的hook可以被安装成全局的,这就好办了,我们不妨用这两个low-level的hook替换掉WH_KEYBORAD和WH_MOUSE,于是开始测试。结果成功了,在C#里实现了全局钩子。

  我们来看一下主要代码段。

  首先倒入所需要的windows函数,主要有三个,SetWindowsHookEX用来安装钩子,UnhookWindowsHookEX用来卸载钩子以及CallNextHookEX用来将hook信息传递到链表中下一个hook处理过程。
[DllImport("user32.dll", CharSet = CharSet.Auto,
           CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        private static extern int SetWindowsHookEx(
            int idHook,
            HookProc lpfn,
            IntPtr hMod,
            int dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        private static extern int UnhookWindowsHookEx(int idHook);

[DllImport("user32.dll", CharSet = CharSet.Auto,
             CallingConvention = CallingConvention.StdCall)]
        private static extern int CallNextHookEx(
            int idHook,
            int nCode,
            int wParam,
            IntPtr lParam);

  下面是有关这两个low-level hook在Winuser.h中的定义:


/// <summary>
        /// Windows NT/2000/XP: Installs a hook procedure that monitors low-level mouse input events.
        /// </summary>
        private const int WH_MOUSE_LL       = 14;
        /// <summary>
        /// Windows NT/2000/XP: Installs a hook procedure that monitors low-level keyboard input events.
        /// </summary>
        private const int WH_KEYBOARD_LL    = 13;

  在安装全局钩子的时候,我们就要做替换了,将WH_MOUSE和WH_KEYBORAD分别换成WH_MOUSE_LL和WH_KEYBORAD_LL:


//install hook
                hMouseHook = SetWindowsHookEx(
                    WH_MOUSE_LL, //原来是WH_MOUSE
                    MouseHookProcedure,
                    Marshal.GetHINSTANCE(
                        Assembly.GetExecutingAssembly().GetModules()[0]),
                    0);

//install hook
                hKeyboardHook = SetWindowsHookEx(
                    WH_KEYBOARD_LL, //原来是WH_KEYBORAD
                    KeyboardHookProcedure,
                    Marshal.GetHINSTANCE(
                    Assembly.GetExecutingAssembly().GetModules()[0]),
                    0);

  这样替换了之后,我们就可以实现全局钩子了,而且,不需要写DLL。看一下程序运行情况:



  下面是关于鼠标和键盘的两个Callback函数:


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

        {

            // if ok and someone listens to our events

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

            {

                //Marshall the data from callback.

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


                //detect button clicked

                MouseButtons button = MouseButtons.None;

                short mouseDelta = 0;

                switch (wParam)

                {

                    case WM_LBUTTONDOWN:

                        //case WM_LBUTTONUP:

                        //case WM_LBUTTONDBLCLK:

                        button = MouseButtons.Left;

                        break;

                    case WM_RBUTTONDOWN:

                        //case WM_RBUTTONUP:

                        //case WM_RBUTTONDBLCLK:

                        button = MouseButtons.Right;

                        break;

                    case 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 == WM_LBUTTONDBLCLK || wParam == WM_RBUTTONDBLCLK) clickCount = 2;

                    else clickCount = 1;


                //generate event

                 MouseEventArgs e = new MouseEventArgs(

                                                    button,

                                                    clickCount,

                                                    mouseHookStruct.pt.x,

                                                    mouseHookStruct.pt.y,

                                                    mouseDelta);

                //raise it

                OnMouseActivity(this, e);

            }

            //call next hook

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

        }


private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
            //indicates if any of underlaing events set e.Handled flag
            bool handled = false;
            //it was ok and someone listens to events
            if ((nCode >= 0) && (KeyDown != null || KeyUp != null || KeyPress != null))
            {
                //read structure KeyboardHookStruct at lParam
                KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
                //raise KeyDown
                if (KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
                {
                    Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
                    KeyEventArgs e = new KeyEventArgs(keyData);
                    KeyDown(this, e);
                    handled = handled || e.Handled;
                }

                // raise KeyPress
                if (KeyPress != null && wParam == WM_KEYDOWN)
                {
                    bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? true : false);
                    bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);

                    byte[] keyState = new byte[256];
                    GetKeyboardState(keyState);
                    byte[] inBuffer = new byte[2];
                    if (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);
                        KeyPress(this, e);
                        handled = handled || e.Handled;
                    }
                }

                // raise KeyUp
                if (KeyUp != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
                {
                    Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
                    KeyEventArgs e = new KeyEventArgs(keyData);
                    KeyUp(this, e);
                    handled = handled || e.Handled;
                }

            }

            //if event handled in application do not handoff to other listeners
            if (handled)
                return 1;
            else
                return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
        }
分享到:
评论

相关推荐

    在C#中使用全局鼠标、键盘Hook

    下面我们将深入探讨如何在C#中设置和使用全局鼠标和键盘Hook。 首先,我们要导入Windows API相关的库。在C#中,我们可以使用`DllImport`特性来引用外部函数。例如,我们需要以下API: 1. `SetWindowsHookEx`: 用于...

    C#中全局鼠标、键盘Hook的应用方法.doc

    在C#中实现全局鼠标和键盘Hook,主要是为了在应用程序之外捕获系统级别的输入事件。全局Hook允许开发者跟踪用户在任何窗口或程序中的鼠标和键盘活动。虽然.NET Framework不直接支持全局Hook,但通过使用WinAPI函数,...

    C#全局鼠标键盘Hook (备查)

    C#全局鼠标键盘Hook (备查) 这个类可以让你得到一个在运行中程序的所有键盘或鼠标事件 并且引发一个带KeyEventArgs参数的.NET事件以便你很容易使用这些信息

    C# 键盘鼠标全局钩子(拦截键盘鼠标所有操作)全局HOOK

    C#实现键盘鼠标全局钩子 VS2013,可编译运行,带DEMO 可全局拦截鼠标单击/双击/滚动事件 可全局拦截键盘按键事件 可锁定键盘鼠标输入,比如锁屏! 该代码无法屏蔽Ctrl +alt +delete 需要实现所有拦截,请参考相关...

    C#使用全局钩子(hook)

    在 C# 开发中,使用全局钩子(hook)来监听键盘鼠标等事件是一种常见的做法。但是,在实际开发中,我们经常会遇到一些问题,例如 SetWindowsHookEx 返回值为 0,或者钩子回调函数不被调用等等。今天,我们就来解决...

    C# 钩子,实现键盘和鼠标的全部事件全局Hook.(完整源码)

    全局的Hook,可以获取MouseMove,MouseClick,MouseDown Up,DoubClick. 滚轮,Press,键盘的KeyPress,keyDown,KeyUp

    C#按键精灵,低级鼠标键盘Hook及发送按键 带源码

    最后,"DLL编写调用"是指在C#项目中使用自定义的动态链接库。DLL文件可以包含一组可重用的函数或方法,多个应用程序可以共享同一个DLL以节省内存和资源。在C#中,我们可以使用`DllImport`特性来导入和调用DLL中的...

    C# Hock 全局监听程序外的键盘和鼠标的事件

    在C#中实现钩子,通常需要使用`SetWindowsHookEx`函数,这个函数是Windows API的一部分,可以通过P/Invoke(Platform Invoke)在.NET环境中使用。首先,你需要定义一个委托类型来匹配钩子回调函数的签名,然后创建一...

    vb.net (c#)中鼠标,键盘钩子Hook

    在VB.NET和C#编程中,鼠标和键盘钩子(Hook)是一种强大的技术,它允许开发者监听和拦截用户的输入事件,无论是鼠标点击还是按键动作。钩子是Windows操作系统提供的一种机制,通过它,一个进程可以获取到另一个进程...

    C#实现的HOOK鼠标和键盘源码

    描述中提到的"老外写的一个可以Hook鼠标和键盘的C#程序源码"表明这个压缩包可能包含了一个完整的示例项目,展示如何在C#中实现全局鼠标和键盘钩子。这个程序可能包含了一个或多个类,这些类使用了`SetWindowsHookEx`...

    C#全局hook实例

    在这个“C#全局Hook实例”中,我们将深入探讨如何在C#环境中实现全局Hook,从而捕获并响应键盘和鼠标事件。 全局Hook,顾名思义,是指在整个系统范围内设置的钩子,它能够监听到任何窗口或进程的指定事件。在...

    C# 全局勾子(Hook 含鼠标键盘窗口内核等)

    C#全局钩子的实现通常涉及到使用C++编写一个动态链接库(DLL),因为Windows API的钩子函数通常是C语言风格的,然后在C#应用程序中调用这个DLL来设置和处理钩子。本文将深入探讨C#全局钩子的实现原理、步骤以及如何...

    c# hook 鼠标键盘事件

    "c# hook 鼠标键盘事件"是指使用C#编程语言来创建一个钩子(hook)程序,这种程序可以监听并处理系统中的鼠标和键盘事件。钩子是Windows API提供的一种机制,允许应用程序设置一个“陷阱”,以便在特定事件发生时...

    C# 全局键盘钩子类(包括鼠标)

    总之,"C#全局键盘钩子类(包括鼠标)"是一个实用的工具,它展示了如何使用C#和Windows API来实现跨进程的键盘和鼠标事件监听。这个"AdrHookDemo"项目是学习和理解全局钩子机制的一个良好起点,通过研究它的代码,...

    基于全局的C#键盘,鼠标钩子类库,示例

    针对标题和描述,本文将深入探讨如何在C#中实现全局的键盘和鼠标钩子,并结合提供的示例进行讲解。 首先,我们需要理解“钩子”(Hook)的概念。在Windows操作系统中,钩子是一种机制,允许应用程序监视系统级事件...

    C#全局鼠标键盘钩子

    总之,全局鼠标键盘钩子在C#中是一个强大的功能,它能帮助开发者监控用户的输入行为。然而,由于其涉及到了系统级别的操作,因此在实际应用中必须谨慎,确保遵循合法和道德的编程实践,避免滥用导致隐私问题。

    c# 全局钩子(使用c++编写的鼠标过程)

    总之,通过C++编写的DLL和C#的混合编程,我们可以实现一个c#全局鼠标钩子,监控和处理系统的鼠标事件。这个过程中涉及到了Windows API的使用、DLL的创建与调用、多语言混合编程以及对操作系统级别的理解。

    c#全局钩子(键盘,鼠标)

    在提供的C#版全局钩子示例中,你可能看到代码是如何创建这些回调函数,如何调用SetWindowsHookEx,以及如何处理接收到的键盘和鼠标事件的。通过研究和理解这个示例,你可以学会如何在自己的C#项目中实现全局钩子功能...

    C# Hook 屏蔽键盘按键

    以下是一个简单的C#代码示例,展示了如何设置全局键盘Hook: ```csharp using System; using System.Runtime.InteropServices; public class KeyboardHook { // 定义键盘Hook常量 private const int WH_KEYBOARD...

    全局鼠标HOOK完整例子

    在这个例子中,"全局鼠标HOOK完整例子" 提供了一个使用C#语言实现的DLL(动态链接库)和一个DEMO程序,它们共同展示了如何设置和使用鼠标HOOK。 首先,我们需要理解什么是HOOK。在Windows操作系统中,HOOK是一种...

Global site tag (gtag.js) - Google Analytics