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: }

原文链接: https://www.cnblogs.com/ihaoqi/p/3239223.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/98630

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月10日 上午4:50
下一篇 2023年2月10日 上午4:51

相关推荐