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