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: }
posted @ 2013-08-05 20:27  爱好奇  阅读(6941)  评论(1编辑  收藏  举报