Allowing mouse events
This commit is contained in:
		
							parent
							
								
									222b43f1d0
								
							
						
					
					
						commit
						f2a7c39abe
					
				| @ -11,7 +11,8 @@ | ||||
| #endif | ||||
| class KeyboardHook { | ||||
| 	#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 | ||||
| 	public: | ||||
| 		struct KeyType { | ||||
| @ -63,9 +64,14 @@ class KeyboardHook { | ||||
| 		long end_id = 0; | ||||
| 	#elif defined(WIN32) | ||||
| 		typedef UINT KeyID; | ||||
| 		HHOOK hook_id = nullptr; | ||||
| 		bool _hook_callback(int, WPARAM, LPARAM); | ||||
| 	#endif | ||||
| 		HHOOK keyboad_hook_id{nullptr}; | ||||
|         HHOOK mouse_hook_id{nullptr}; | ||||
| 
 | ||||
|         bool keyboard_hook_callback(int, WPARAM, LPARAM); | ||||
|         bool mouse_hook_callback(int, WPARAM, LPARAM); | ||||
|     #endif | ||||
|          | ||||
|         void trigger_key_event(const enum KeyEvent::type&, const std::string& /* key */); | ||||
| 
 | ||||
| 		std::map<KeyID, bool> map_key; | ||||
| 		std::map<KeyID, KeyID> map_special; | ||||
|  | ||||
| @ -1,11 +1,12 @@ | ||||
| #include <iostream> | ||||
| #include <cassert> | ||||
| #include <string> | ||||
| #include "KeyboardHook.h" | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| typedef KBDLLHOOKSTRUCT KeyboardHookStruct; | ||||
| LRESULT CALLBACK keyboard_hook_callback(int, WPARAM, LPARAM); | ||||
| typedef MSLLHOOKSTRUCT MouseHookStruct; | ||||
| std::map<thread::id, KeyboardHook*> hook_handles; | ||||
| 
 | ||||
| KeyboardHook::KeyboardHook() {} | ||||
| @ -14,6 +15,21 @@ KeyboardHook::~KeyboardHook() { | ||||
| 		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() { | ||||
| 	assert(!this->_attached); | ||||
| 	this->active = true; | ||||
| @ -36,33 +52,49 @@ void KeyboardHook::detach() { | ||||
| 	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() { | ||||
| 	hook_handles[this_thread::get_id()] = this; | ||||
| 	this->hook_id = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook_callback, GetModuleHandle(nullptr), 0); | ||||
| 	if(!this->hook_id) { | ||||
| 		cerr << "Failed to register hook!" << endl; | ||||
| 	this->keyboad_hook_id = SetWindowsHookEx(WH_KEYBOARD_LL, _keyboard_hook_callback, GetModuleHandle(nullptr), 0); | ||||
| 	if(!this->keyboad_hook_id) { | ||||
| 		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; | ||||
|     } | ||||
| 
 | ||||
| 	MSG msg; | ||||
| 	while(!GetMessage(&msg, nullptr, 0, 0) && this->active) { | ||||
| 		TranslateMessage(&msg); | ||||
| 		DispatchMessage(&msg); | ||||
| 	} | ||||
| 
 | ||||
| 	UnhookWindowsHookEx(this->hook_id); | ||||
| 	UnhookWindowsHookEx(this->keyboad_hook_id); | ||||
| 	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) { | ||||
| 	auto scan_code = MapVirtualKey(code, MAPVK_VK_TO_VSC); | ||||
| 	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; | ||||
| 	if(event == WM_KEYDOWN || event == WM_SYSKEYDOWN) { | ||||
| 		auto& state = this->map_key[keyboard->vkCode]; | ||||
| @ -117,40 +149,9 @@ bool KeyboardHook::_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) | ||||
| 		else | ||||
| 			this->map_special[type] = keyboard->vkCode; | ||||
| 
 | ||||
| 		if (this->callback_event) { | ||||
| 			if(!typed) { | ||||
| 				auto e = make_shared<KeyboardHook::KeyEvent>(); | ||||
| 				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); | ||||
| 			} | ||||
| 		} | ||||
|         if(!typed) | ||||
|             this->trigger_key_event(KeyEvent::PRESS, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_code(this->map_special[KeyType::KEY_NORMAL], false)); | ||||
|         this->trigger_key_event(KeyEvent::TYPE, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_code(this->map_special[KeyType::KEY_NORMAL], false)); | ||||
| 	} else if(event == WM_KEYUP || event == WM_SYSKEYUP) { | ||||
| 		auto& state = this->map_key[keyboard->vkCode]; | ||||
| 		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) | ||||
| 			this->map_special[type] = false; | ||||
| 		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) { | ||||
| 			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); | ||||
| 		} | ||||
|         this->trigger_key_event(KeyEvent::RELEASE, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_code(this->map_special[KeyType::KEY_NORMAL], false)); | ||||
| 	} | ||||
| 
 | ||||
| 	//Consume the event: return 1
 | ||||
| 	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