• C++实现全局鼠标、键盘消息hook,支持事件


    目前在开发一个小的界面程序,需要用到消息hook于是写了一个CGlobalWindowMsgHook类,使用起来非常方便,现拿出来与大家分享。

    头文件:

       1: #pragma once
       2:  
       3: #include "EventDelegate.h"
       4:  
       5: /////////////////////////////////////////////////////////////////////////////////////////
       6: // CGlobalWindowMsgHook 全局 Windows 消息 Hook
       7: //
       8:  
       9: class CKeyEventArgs : public CEventArgs
      10: {
      11: public:
      12:     CKeyEventArgs (DWORD code);
      13:  
      14:     DWORD   vkCode;
      15: };
      16:  
      17: // Specifies constants that define which mouse button was pressed.
      18: enum MouseButtons
      19: {
      20:     None        = 0,        // No mouse button was pressed.
      21:     Left        = 1048576,    // The left mouse button was pressed.
      22:     Right        = 2097152,    // The right mouse button was pressed.
      23:     Middle        = 4194304,    // The middle mouse button was pressed.
      24:     XButton1    = 8388608,    // The first XButton was pressed.
      25:     XButton2    = 16777216,// The second XButton was pressed.
      26: };
      27:  
      28: class CMouseEventArgs : public CEventArgs
      29: {
      30: public:
      31:     CMouseEventArgs (MouseButtons button1, int clicks1, int x1, int y1, int delta1);
      32:  
      33:     MouseButtons button; int clicks; int x; int y; int delta;
      34: };
      35:  
      36: // void handler (IEventSource* sender, CMouseEventArgs* e);
      37: DEFINE_EVENT_HANDLER (CMouseEventDelegate, CMouseEventArgs);
      38:  
      39: // void handler (IEventSource* sender, CKeyEventArgs* e);
      40: DEFINE_EVENT_HANDLER (CKeyEventDelegate, CKeyEventArgs);
      41:  
      42: class CGlobalWindowMsgHook : public IEventSource
      43: {
      44: private:
      45:     CGlobalWindowMsgHook (void);
      46:  
      47: public:
      48:     ~CGlobalWindowMsgHook (void);
      49:  
      50:     // 获取消息hook实例
      51:     static CGlobalWindowMsgHook* instance (void);
      52:  
      53:     // Occours when the hook captures a mouse click
      54:     CMouseEventDelegate MouseClick;
      55:  
      56:     // Occours when the hook captures a mouse double click
      57:     CMouseEventDelegate MouseDblClick;
      58:  
      59:     // Occours when the hook captures the mouse wheel
      60:     CMouseEventDelegate MouseWheel;
      61:  
      62:     // Occours when the hook captures the press of a mouse button
      63:     CMouseEventDelegate MouseDown;
      64:  
      65:     // Occours when the hook captures the release of a mouse button
      66:     CMouseEventDelegate MouseUp;
      67:  
      68:     // Occours when the hook captures the mouse moving over the screen
      69:     CMouseEventDelegate MouseMove;
      70:  
      71:     // Occours when a key is pressed
      72:     CKeyEventDelegate KeyDown;
      73:  
      74:     // Occours when a key is released
      75:     CKeyEventDelegate KeyUp;
      76:  
      77:     // Occours when a key is pressed
      78:     CKeyEventDelegate KeyPress;
      79:  
      80: protected:
      81:     static LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
      82:     static LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam);
      83:  
      84:     static HHOOK _hMouseHook;
      85:     static HHOOK _hKeyboardHook;
      86:  
      87:     static std::auto_ptr<CGlobalWindowMsgHook> _pInstance;
      88: };

    实现文件:

       1: #include "stdafx.h"
       2: #include "GlobalWindowMsgHook.h"
       3:  
       4: /////////////////////////////////////////////////////////////////////////////////////////
       5: // CGlobalWindowMsgHook 全局 Windows 消息 Hook
       6: //
       7:  
       8: CKeyEventArgs::CKeyEventArgs (DWORD code)
       9: {
      10:     vkCode = code;
      11: }
      12:  
      13: CMouseEventArgs::CMouseEventArgs (MouseButtons button1, int clicks1, int x1, int y1, int delta1)
      14: {
      15:     button = button1;
      16:     clicks = clicks1;
      17:     x = x1; y = y1; delta = delta1;
      18: }
      19:  
      20: HHOOK CGlobalWindowMsgHook::_hMouseHook = NULL;
      21: HHOOK CGlobalWindowMsgHook::_hKeyboardHook = NULL;
      22:  
      23: std::auto_ptr<CGlobalWindowMsgHook> CGlobalWindowMsgHook::_pInstance;
      24:  
      25: CGlobalWindowMsgHook::CGlobalWindowMsgHook (void)
      26: {
      27:     _hMouseHook = SetWindowsHookEx (WH_MOUSE_LL, MouseProc, NULL, NULL);
      28:     _hKeyboardHook = SetWindowsHookEx (WH_KEYBOARD_LL, KeyboardProc, NULL, NULL);
      29: }
      30:  
      31: CGlobalWindowMsgHook::~CGlobalWindowMsgHook (void)
      32: {
      33:     if (_hMouseHook)
      34:     {
      35:         UnhookWindowsHookEx (_hMouseHook);
      36:     }
      37:  
      38:     if (_hKeyboardHook)
      39:     {
      40:         UnhookWindowsHookEx (_hKeyboardHook);
      41:     }
      42: }
      43:  
      44: // 获取消息hook实例
      45: CGlobalWindowMsgHook* CGlobalWindowMsgHook::instance (void)
      46: {
      47:     if (!_pInstance.get())
      48:     {
      49:         _pInstance.reset (new CGlobalWindowMsgHook ());
      50:     }
      51:  
      52:     return _pInstance.get();
      53: }
      54:  
      55: LRESULT CGlobalWindowMsgHook::KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
      56: {
      57:     CGlobalWindowMsgHook* This = instance();
      58:     PKBDLLHOOKSTRUCT hookStruct = (PKBDLLHOOKSTRUCT)lParam;
      59:     BOOL bHandled = FALSE;
      60:  
      61:     int msg = wParam;
      62:     if (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN)
      63:     {
      64:         CKeyEventArgs e (hookStruct->vkCode);
      65:         This->KeyDown.Fire (This, &e);
      66:         bHandled = e.bHandled;
      67:     }
      68:     else if (msg == WM_KEYUP || msg == WM_SYSKEYUP)
      69:     {
      70:         CKeyEventArgs e (hookStruct->vkCode);
      71:         This->KeyUp.Fire (This, &e);
      72:         bHandled = e.bHandled;
      73:     }
      74:  
      75:     if (msg == WM_KEYDOWN && This->KeyPress.GetCount ())
      76:     {
      77:         BYTE keyState[256] = { 0 };
      78:         BYTE buffer[2] = { 0 };
      79:         GetKeyboardState(keyState);
      80:         int conversion = ToAscii(hookStruct->vkCode, hookStruct->scanCode, keyState, (LPWORD) buffer, hookStruct->flags);
      81:  
      82:         if (conversion == 1 || conversion == 2)
      83:         {
      84:             BOOL shift = (GetKeyState(VK_SHIFT) & 0x80) == 0x80;
      85:             BOOL capital = GetKeyState(VK_CAPITAL) != 0;
      86:             CHAR c = (CHAR)buffer[0];
      87:             if ((shift ^ capital) && isalpha(c))
      88:             {
      89:                 c = tolower(c);
      90:             }
      91:             CKeyEventArgs e (c);
      92:             This->KeyPress.Fire (This, &e);
      93:             bHandled |= e.bHandled;
      94:         }
      95:     }
      96:  
      97:     return bHandled ? 1 : CallNextHookEx(_hKeyboardHook, nCode, wParam, lParam);
      98: }
      99:  
     100: LRESULT CGlobalWindowMsgHook::MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
     101: {
     102:     CGlobalWindowMsgHook* This = instance();
     103:     PMSLLHOOKSTRUCT hookStruct = (PMSLLHOOKSTRUCT)lParam;
     104:  
     105:     int msg = wParam;
     106:     int x = hookStruct->pt.x;
     107:     int y = hookStruct->pt.y;
     108:     int delta = (short)((hookStruct->mouseData >> 16) & 0xffff);
     109:     
     110:     if (msg == WM_MOUSEWHEEL)
     111:     {
     112:         This->MouseWheel.Fire (This, &CMouseEventArgs (None, 0, x, y, delta));
     113:     }
     114:     else if (msg == WM_MOUSEMOVE)
     115:     {
     116:         This->MouseMove.Fire (This, &CMouseEventArgs (None, 0, x, y, delta));
     117:     }
     118:     else if (msg == WM_LBUTTONDBLCLK)
     119:     {
     120:         This->MouseDblClick.Fire (This, &CMouseEventArgs (Left, 0, x, y, delta));
     121:     }
     122:     else if (msg == WM_LBUTTONDOWN)
     123:     {
     124:         This->MouseDown.Fire (This, &CMouseEventArgs (Left, 0, x, y, delta));
     125:     }
     126:     else if (msg == WM_LBUTTONUP)
     127:     {
     128:         This->MouseUp.Fire (This, &CMouseEventArgs (Left, 0, x, y, delta));
     129:         This->MouseClick.Fire (This, &CMouseEventArgs (Left, 0, x, y, delta));
     130:     }
     131:     else if (msg == WM_MBUTTONDBLCLK)
     132:     {
     133:         This->MouseDblClick.Fire (This, &CMouseEventArgs (Middle, 0, x, y, delta));
     134:     }
     135:     else if (msg == WM_MBUTTONDOWN)
     136:     {
     137:         This->MouseDown.Fire (This, &CMouseEventArgs (Middle, 0, x, y, delta));
     138:     }
     139:     else if (msg == WM_MBUTTONUP)
     140:     {
     141:         This->MouseUp.Fire (This, &CMouseEventArgs (Middle, 0, x, y, delta));
     142:     }
     143:     else if (msg == WM_RBUTTONDBLCLK)
     144:     {
     145:         This->MouseDblClick.Fire (This, &CMouseEventArgs (Right, 0, x, y, delta));
     146:     }
     147:     else if (msg == WM_RBUTTONDOWN)
     148:     {
     149:         This->MouseDown.Fire (This, &CMouseEventArgs (Right, 0, x, y, delta));
     150:     }
     151:     else if (msg == WM_RBUTTONUP)
     152:     {
     153:         This->MouseUp.Fire (This, &CMouseEventArgs (Right, 0, x, y, delta));
     154:     }
     155:     else if (msg == WM_XBUTTONDBLCLK)
     156:     {
     157:         This->MouseDblClick.Fire (This, &CMouseEventArgs (XButton1, 0, x, y, delta));
     158:     }
     159:     else if (msg == WM_XBUTTONDOWN)
     160:     {
     161:         This->MouseDown.Fire (This, &CMouseEventArgs (XButton1, 0, x, y, delta));
     162:     }
     163:     else if (msg == WM_XBUTTONUP)
     164:     {
     165:         This->MouseUp.Fire (This, &CMouseEventArgs (XButton1, 0, x, y, delta));
     166:     }
     167:     
     168:     return CallNextHookEx(_hMouseHook, nCode, wParam, lParam);
     169: }

    使用方法:

       1: class CPopupPanelManager
       2: {
       3: protected:
       4:     // 首先在使用类中定义要实现的事件句柄
       5:     void _keyboardHook_KeyDown(IEventSource* sender, CKeyEventArgs* e);
       6:     void _mouseHook_MouseWheel(IEventSource* sender, CMouseEventArgs* e);
       7:     void _mouseHook_MouseDown(IEventSource* sender, CMouseEventArgs* e);
       8: }
       9:  
      10: // 然后在实现在添加登记事件处理、注销事件处理的代码
      11: CPopupPanelManager::CPopupPanelManager (void)
      12: {
      13:     // 注册hook
      14:     CGlobalWindowMsgHook* hook = CGlobalWindowMsgHook::instance();
      15:     hook->MouseDown += MakeDelegate (this, &CPopupPanelManager::_mouseHook_MouseDown);
      16:     hook->MouseWheel += MakeDelegate (this, &CPopupPanelManager::_mouseHook_MouseWheel);
      17:     hook->KeyDown += MakeDelegate (this, &CPopupPanelManager::_keyboardHook_KeyDown);
      18: }
      19:  
      20: CPopupPanelManager::~CPopupPanelManager (void)
      21: {
      22:     // 取消hook
      23:     CGlobalWindowMsgHook* hook = CGlobalWindowMsgHook::instance();
      24:     hook->MouseDown -= MakeDelegate (this, &CPopupPanelManager::_mouseHook_MouseDown);
      25:     hook->MouseWheel -= MakeDelegate (this, &CPopupPanelManager::_mouseHook_MouseWheel);
      26:     hook->KeyDown -= MakeDelegate (this, &CPopupPanelManager::_keyboardHook_KeyDown);
      27: }
      28:  
      29: // 最后在cpp上实现句柄
      30: void CPopupPanelManager::_mouseHook_MouseDown(IEventSource* sender, CMouseEventArgs* e)
      31: {
      32:  
      33: }
      34:  
      35:  
      36: void CPopupPanelManager::_mouseHook_MouseWheel(IEventSource* sender, CMouseEventArgs* e)
      37: {
      38:  
      39: }
      40:  
      41: void CPopupPanelManager::_keyboardHook_KeyDown(IEventSource* sender, CKeyEventArgs* e)
      42: {
      43:     if (e->vkCode == VK_ESCAPE)
      44:     {
      45:        
      46:     }
      47: }
  • 相关阅读:
    ubuntu 15.04默认root用户登陆
    hive的not in
    Spark 1.4.1中Beeline使用的gc overhead limit exceeded
    Sequoiadb该如何选择合适的SQL引擎
    scala的object知识点
    scala中同步块
    英语口语练习系列-C36-城市-谈论活动-登高
    英语口语练习系列-C35-马戏-谈论语言-己亥杂诗
    英语口语练习系列-C34-儿童-谈论物品和人-武陵春
    英语口语练习系列-C33-露营-谈论日期-离思
  • 原文地址:https://www.cnblogs.com/ihaoqi/p/3239223.html
Copyright © 2020-2023  润新知