Allowing mouse events
This commit is contained in:
		
							parent
							
								
									222b43f1d0
								
							
						
					
					
						commit
						f2a7c39abe
					
				| @ -11,7 +11,8 @@ | |||||||
| #endif | #endif | ||||||
| class KeyboardHook { | class KeyboardHook { | ||||||
| 	#if defined(WIN32) | 	#if defined(WIN32) | ||||||
| 		friend LRESULT CALLBACK keyboard_hook_callback(int, WPARAM, LPARAM); | 		friend LRESULT CALLBACK _keyboard_hook_callback(int, WPARAM, LPARAM); | ||||||
|  |         friend LRESULT CALLBACK _mouse_hook_callback(int, WPARAM, LPARAM); | ||||||
| 	#endif | 	#endif | ||||||
| 	public: | 	public: | ||||||
| 		struct KeyType { | 		struct KeyType { | ||||||
| @ -63,10 +64,15 @@ class KeyboardHook { | |||||||
| 		long end_id = 0; | 		long end_id = 0; | ||||||
| 	#elif defined(WIN32) | 	#elif defined(WIN32) | ||||||
| 		typedef UINT KeyID; | 		typedef UINT KeyID; | ||||||
| 		HHOOK hook_id = nullptr; | 		HHOOK keyboad_hook_id{nullptr}; | ||||||
| 		bool _hook_callback(int, WPARAM, LPARAM); |         HHOOK mouse_hook_id{nullptr}; | ||||||
|  | 
 | ||||||
|  |         bool keyboard_hook_callback(int, WPARAM, LPARAM); | ||||||
|  |         bool mouse_hook_callback(int, WPARAM, LPARAM); | ||||||
|     #endif |     #endif | ||||||
|          |          | ||||||
|  |         void trigger_key_event(const enum KeyEvent::type&, const std::string& /* key */); | ||||||
|  | 
 | ||||||
| 		std::map<KeyID, bool> map_key; | 		std::map<KeyID, bool> map_key; | ||||||
| 		std::map<KeyID, KeyID> map_special; | 		std::map<KeyID, KeyID> map_special; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,11 +1,12 @@ | |||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <cassert> | #include <cassert> | ||||||
|  | #include <string> | ||||||
| #include "KeyboardHook.h" | #include "KeyboardHook.h" | ||||||
| 
 | 
 | ||||||
| using namespace std; | using namespace std; | ||||||
| 
 | 
 | ||||||
| typedef KBDLLHOOKSTRUCT KeyboardHookStruct; | typedef KBDLLHOOKSTRUCT KeyboardHookStruct; | ||||||
| LRESULT CALLBACK keyboard_hook_callback(int, WPARAM, LPARAM); | typedef MSLLHOOKSTRUCT MouseHookStruct; | ||||||
| std::map<thread::id, KeyboardHook*> hook_handles; | std::map<thread::id, KeyboardHook*> hook_handles; | ||||||
| 
 | 
 | ||||||
| KeyboardHook::KeyboardHook() {} | KeyboardHook::KeyboardHook() {} | ||||||
| @ -14,6 +15,21 @@ KeyboardHook::~KeyboardHook() { | |||||||
| 		this->detach(); | 		this->detach(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void KeyboardHook::trigger_key_event(const enum KeyEvent::type& type, const std::string &key) { | ||||||
|  |     if(!this->callback_event) return; | ||||||
|  |      | ||||||
|  |     auto event = make_shared<KeyboardHook::KeyEvent>(); | ||||||
|  |     event->type = type; | ||||||
|  |     event->code = key; | ||||||
|  | 
 | ||||||
|  |     event->key_alt = this->map_special[KeyType::KEY_ALT]; | ||||||
|  |     event->key_ctrl = this->map_special[KeyType::KEY_CTRL]; | ||||||
|  |     event->key_windows = this->map_special[KeyType::KEY_WIN]; | ||||||
|  |     event->key_shift = this->map_special[KeyType::KEY_SHIFT]; | ||||||
|  | 
 | ||||||
|  |     this->callback_event(event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool KeyboardHook::attach() { | bool KeyboardHook::attach() { | ||||||
| 	assert(!this->_attached); | 	assert(!this->_attached); | ||||||
| 	this->active = true; | 	this->active = true; | ||||||
| @ -36,11 +52,36 @@ void KeyboardHook::detach() { | |||||||
| 	this->_attached = false; | 	this->_attached = false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | LRESULT _keyboard_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) { | ||||||
|  |     auto handle = hook_handles[this_thread::get_id()]; | ||||||
|  |     assert(handle); | ||||||
|  |     auto consume = handle->keyboard_hook_callback(nCode, event, ptr_keyboard); | ||||||
|  |     if(consume) | ||||||
|  |         return 1; | ||||||
|  |     return CallNextHookEx(nullptr, nCode, event, ptr_keyboard); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | LRESULT _mouse_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) { | ||||||
|  |     auto handle = hook_handles[this_thread::get_id()]; | ||||||
|  |     assert(handle); | ||||||
|  |     auto consume = handle->mouse_hook_callback(nCode, event, ptr_keyboard); | ||||||
|  |     if(consume) | ||||||
|  |         return 1; | ||||||
|  |     return CallNextHookEx(nullptr, nCode, event, ptr_keyboard); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void KeyboardHook::poll_events() { | void KeyboardHook::poll_events() { | ||||||
| 	hook_handles[this_thread::get_id()] = this; | 	hook_handles[this_thread::get_id()] = this; | ||||||
| 	this->hook_id = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook_callback, GetModuleHandle(nullptr), 0); | 	this->keyboad_hook_id = SetWindowsHookEx(WH_KEYBOARD_LL, _keyboard_hook_callback, GetModuleHandle(nullptr), 0); | ||||||
| 	if(!this->hook_id) { | 	if(!this->keyboad_hook_id) { | ||||||
| 		cerr << "Failed to register hook!" << endl; | 		cerr << "Failed to register keyboard hook" << endl; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  |     this->mouse_hook_id = SetWindowsHookEx(WH_MOUSE_LL, _mouse_hook_callback, GetModuleHandle(nullptr), 0); | ||||||
|  |     if(!this->keyboad_hook_id) { | ||||||
|  |         UnhookWindowsHookEx(this->keyboad_hook_id); | ||||||
|  |         cerr << "Failed to register mouse hook" << endl; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -50,19 +91,10 @@ void KeyboardHook::poll_events() { | |||||||
| 		DispatchMessage(&msg); | 		DispatchMessage(&msg); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	UnhookWindowsHookEx(this->hook_id); | 	UnhookWindowsHookEx(this->keyboad_hook_id); | ||||||
| 	hook_handles[this_thread::get_id()] = nullptr; | 	hook_handles[this_thread::get_id()] = nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| LRESULT keyboard_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) { |  | ||||||
| 	auto handle = hook_handles[this_thread::get_id()]; |  | ||||||
| 	assert(handle); |  | ||||||
| 	auto consume = handle->_hook_callback(nCode, event, ptr_keyboard); |  | ||||||
| 	if(consume) |  | ||||||
| 		return 1; |  | ||||||
| 	return CallNextHookEx(nullptr, nCode, event, ptr_keyboard); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| inline std::string key_code(DWORD code, bool extended = false) { | inline std::string key_code(DWORD code, bool extended = false) { | ||||||
| 	auto scan_code = MapVirtualKey(code, MAPVK_VK_TO_VSC); | 	auto scan_code = MapVirtualKey(code, MAPVK_VK_TO_VSC); | ||||||
| 	if(extended) | 	if(extended) | ||||||
| @ -104,7 +136,7 @@ inline KeyType::value key_type(DWORD vk_code) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool KeyboardHook::_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) { | bool KeyboardHook::keyboard_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) { | ||||||
| 	auto keyboard = (KeyboardHookStruct*) ptr_keyboard; | 	auto keyboard = (KeyboardHookStruct*) ptr_keyboard; | ||||||
| 	if(event == WM_KEYDOWN || event == WM_SYSKEYDOWN) { | 	if(event == WM_KEYDOWN || event == WM_SYSKEYDOWN) { | ||||||
| 		auto& state = this->map_key[keyboard->vkCode]; | 		auto& state = this->map_key[keyboard->vkCode]; | ||||||
| @ -117,40 +149,9 @@ bool KeyboardHook::_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) | |||||||
| 		else | 		else | ||||||
| 			this->map_special[type] = keyboard->vkCode; | 			this->map_special[type] = keyboard->vkCode; | ||||||
| 
 | 
 | ||||||
| 		if (this->callback_event) { |         if(!typed) | ||||||
| 			if(!typed) { |             this->trigger_key_event(KeyEvent::PRESS, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_code(this->map_special[KeyType::KEY_NORMAL], false)); | ||||||
| 				auto e = make_shared<KeyboardHook::KeyEvent>(); |         this->trigger_key_event(KeyEvent::TYPE, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_code(this->map_special[KeyType::KEY_NORMAL], false)); | ||||||
| 				e->type = KeyboardHook::KeyEvent::PRESS; |  | ||||||
| 				if(type == KeyType::KEY_NORMAL) { |  | ||||||
| 					e->code = key_code(keyboard); |  | ||||||
| 				} else { |  | ||||||
| 					e->code = key_code(this->map_special[KeyType::KEY_NORMAL], false); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				e->key_alt = this->map_special[KeyType::KEY_ALT]; |  | ||||||
| 				e->key_ctrl = this->map_special[KeyType::KEY_CTRL]; |  | ||||||
| 				e->key_windows = this->map_special[KeyType::KEY_WIN]; |  | ||||||
| 				e->key_shift = this->map_special[KeyType::KEY_SHIFT]; |  | ||||||
| 
 |  | ||||||
| 				this->callback_event(e); |  | ||||||
| 			} |  | ||||||
| 			{ |  | ||||||
| 				auto e = make_shared<KeyboardHook::KeyEvent>(); |  | ||||||
| 				e->type = KeyboardHook::KeyEvent::TYPE; |  | ||||||
| 				if(type == KeyType::KEY_NORMAL) { |  | ||||||
| 					e->code = key_code(keyboard); |  | ||||||
| 				} else { |  | ||||||
| 					e->code = key_code(this->map_special[KeyType::KEY_NORMAL], false); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				e->key_alt = this->map_special[KeyType::KEY_ALT]; |  | ||||||
| 				e->key_ctrl = this->map_special[KeyType::KEY_CTRL]; |  | ||||||
| 				e->key_windows = this->map_special[KeyType::KEY_WIN]; |  | ||||||
| 				e->key_shift = this->map_special[KeyType::KEY_SHIFT]; |  | ||||||
| 
 |  | ||||||
| 				this->callback_event(e); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} else if(event == WM_KEYUP || event == WM_SYSKEYUP) { | 	} else if(event == WM_KEYUP || event == WM_SYSKEYUP) { | ||||||
| 		auto& state = this->map_key[keyboard->vkCode]; | 		auto& state = this->map_key[keyboard->vkCode]; | ||||||
| 		if(!state) return false; //Duplicate
 | 		if(!state) return false; //Duplicate
 | ||||||
| @ -160,26 +161,36 @@ bool KeyboardHook::_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) | |||||||
| 		if(type != KeyType::KEY_NORMAL) | 		if(type != KeyType::KEY_NORMAL) | ||||||
| 			this->map_special[type] = false; | 			this->map_special[type] = false; | ||||||
| 		else if(this->map_special[KeyType::KEY_NORMAL] == keyboard->vkCode) | 		else if(this->map_special[KeyType::KEY_NORMAL] == keyboard->vkCode) | ||||||
| 			this->map_special[KeyType::KEY_NORMAL] = 0xFF; | 			this->map_special[KeyType::KEY_NORMAL] = 0; | ||||||
| 
 | 
 | ||||||
| 		if (this->callback_event) { |         this->trigger_key_event(KeyEvent::RELEASE, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_code(this->map_special[KeyType::KEY_NORMAL], false)); | ||||||
| 			auto e = make_shared<KeyboardHook::KeyEvent>(); |  | ||||||
| 			e->type = KeyboardHook::KeyEvent::RELEASE; |  | ||||||
| 			if(type == KeyType::KEY_NORMAL) { |  | ||||||
| 				e->code = key_code(keyboard); |  | ||||||
| 			} else { |  | ||||||
| 				e->code = key_code(this->map_special[KeyType::KEY_NORMAL], false); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			e->key_alt = this->map_special[KeyType::KEY_ALT]; |  | ||||||
| 			e->key_ctrl = this->map_special[KeyType::KEY_CTRL]; |  | ||||||
| 			e->key_windows = this->map_special[KeyType::KEY_WIN]; |  | ||||||
| 			e->key_shift = this->map_special[KeyType::KEY_SHIFT]; |  | ||||||
| 
 |  | ||||||
| 			this->callback_event(e); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	//Consume the event: return 1
 | 	//Consume the event: return 1
 | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | bool KeyboardHook::mouse_hook_callback(int nCode, WPARAM event, LPARAM ptr_mouse) {  | ||||||
|  |     auto mouse = (MouseHookStruct*) ptr_mouse; | ||||||
|  |     if(event == WM_RBUTTONDOWN) | ||||||
|  |         this->trigger_key_event(KeyEvent::PRESS, "MOUSE1"); | ||||||
|  |     else if(event == WM_RBUTTONUP) | ||||||
|  |         this->trigger_key_event(KeyEvent::RELEASE, "MOUSE1"); | ||||||
|  |     if(event == WM_LBUTTONDOWN) | ||||||
|  |         this->trigger_key_event(KeyEvent::PRESS, "MOUSE2"); | ||||||
|  |     else if(event == WM_LBUTTONUP) | ||||||
|  |         this->trigger_key_event(KeyEvent::RELEASE, "MOUSE2"); | ||||||
|  |     if(event == WM_MBUTTONDOWN) | ||||||
|  |         this->trigger_key_event(KeyEvent::PRESS, "MOUSE3"); | ||||||
|  |     else if(event == WM_MBUTTONUP)  | ||||||
|  |         this->trigger_key_event(KeyEvent::RELEASE, "MOUSE3"); | ||||||
|  |     else if(event == WM_XBUTTONDOWN || event == WM_XBUTTONUP) {  | ||||||
|  |         auto x_index = GET_XBUTTON_WPARAM(mouse->mouseData); | ||||||
|  |         this->trigger_key_event(event == WM_XBUTTONDOWN ? KeyEvent::PRESS : KeyEvent::RELEASE, "MOUSEX" + std::to_string(x_index)); | ||||||
|  |     } | ||||||
|  |     else if(event == WM_MOUSEMOVE) | ||||||
|  |         ; | ||||||
|  |     else | ||||||
|  |         cout << "Unknown event: " << event << endl; | ||||||
|  |     return false; | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user