C# 在程序焦点之外捕捉按键操作(键盘钩子的使用)

本文主要是介绍C# 在程序焦点之外捕捉按键操作(键盘钩子的使用),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在程序中捕捉用户的按键行为很容易,但是假如程序最小化了或者隐藏到系统托盘了,这时因为程序已经失去焦点了我们想捕捉按键行为就不是那么容易了。怎么办呢?这就要使用键盘钩子了。

关于键盘钩子,下面这个网友描述的很详尽,我就不班门弄斧了,转载过来以备不时之需。原文:http://www.cnblogs.com/hocylan/archive/2008/01/14/1038390.html


概要

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

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

3 步骤:

   A 安装钩子

   B 回调函数

   C 处理函数

   D 普通业务处理

   ……

4 完成

下载源程序和运行程序

http://files.cnblogs.com/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


这篇关于C# 在程序焦点之外捕捉按键操作(键盘钩子的使用)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1008466

相关文章

Golang interface{}的具体使用

《Golanginterface{}的具体使用》interface{}是Go中可以表示任意类型的空接口,本文主要介绍了Golanginterface{}的具体使用,具有一定的参考价值,感兴趣的可以了... 目录一、什么是 interface{}?定义形China编程式:二、interface{} 有什么特别的?✅

使用Python实现调用API获取图片存储到本地的方法

《使用Python实现调用API获取图片存储到本地的方法》开发一个自动化工具,用于从JSON数据源中提取图像ID,通过调用指定API获取未经压缩的原始图像文件,并确保下载结果与Postman等工具直接... 目录使用python实现调用API获取图片存储到本地1、项目概述2、核心功能3、环境准备4、代码实现

windows和Linux安装Jmeter与简单使用方式

《windows和Linux安装Jmeter与简单使用方式》:本文主要介绍windows和Linux安装Jmeter与简单使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Windows和linux安装Jmeter与简单使用一、下载安装包二、JDK安装1.windows设

Spring 缓存在项目中的使用详解

《Spring缓存在项目中的使用详解》Spring缓存机制,Cache接口为缓存的组件规范定义,包扩缓存的各种操作(添加缓存、删除缓存、修改缓存等),本文给大家介绍Spring缓存在项目中的使用... 目录1.Spring 缓存机制介绍2.Spring 缓存用到的概念Ⅰ.两个接口Ⅱ.三个注解(方法层次)Ⅲ.

PyTorch中cdist和sum函数使用示例详解

《PyTorch中cdist和sum函数使用示例详解》torch.cdist是PyTorch中用于计算**两个张量之间的成对距离(pairwisedistance)**的函数,常用于点云处理、图神经网... 目录基本语法输出示例1. 简单的 2D 欧几里得距离2. 批量形式(3D Tensor)3. 使用不

C#使用MQTTnet实现服务端与客户端的通讯的示例

《C#使用MQTTnet实现服务端与客户端的通讯的示例》本文主要介绍了C#使用MQTTnet实现服务端与客户端的通讯的示例,包括协议特性、连接管理、QoS机制和安全策略,具有一定的参考价值,感兴趣的可... 目录一、MQTT 协议简介二、MQTT 协议核心特性三、MQTTNET 库的核心功能四、服务端(BR

无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案

《无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案》:本文主要介绍了无法启动此程序,详细内容请阅读本文,希望能对你有所帮助... 在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是"api-ms-win-core-path-l1-1-0.dll丢失

使用@Cacheable注解Redis时Redis宕机或其他原因连不上继续调用原方法的解决方案

《使用@Cacheable注解Redis时Redis宕机或其他原因连不上继续调用原方法的解决方案》在SpringBoot应用中,我们经常使用​​@Cacheable​​注解来缓存数据,以提高应用的性能... 目录@Cacheable注解Redis时,Redis宕机或其他原因连不上,继续调用原方法的解决方案1

java中XML的使用全过程

《java中XML的使用全过程》:本文主要介绍java中XML的使用全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录什么是XML特点XML作用XML的编写语法基本语法特殊字符编写约束XML的书写格式DTD文档schema文档解析XML的方法​​DOM解析XM

C#继承之里氏替换原则分析

《C#继承之里氏替换原则分析》:本文主要介绍C#继承之里氏替换原则,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#里氏替换原则一.概念二.语法表现三.类型检查与转换总结C#里氏替换原则一.概念里氏替换原则是面向对象设计的基本原则之一:核心思想:所有引py