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

相关文章

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

MyBatis ParameterHandler的具体使用

《MyBatisParameterHandler的具体使用》本文主要介绍了MyBatisParameterHandler的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、概述二、源码1 关键属性2.setParameters3.TypeHandler1.TypeHa

Spring 中的切面与事务结合使用完整示例

《Spring中的切面与事务结合使用完整示例》本文给大家介绍Spring中的切面与事务结合使用完整示例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录 一、前置知识:Spring AOP 与 事务的关系 事务本质上就是一个“切面”二、核心组件三、完