1+ #pragma once
2+ #include < windows.h>
3+ #include < unordered_map>
4+ #include < functional>
5+ #include < iostream> // For logging
6+
7+ class HotkeyManager {
8+ public:
9+ HotkeyManager () : nextHotkeyId(1 ) {
10+ std::cout << " HotkeyManager initialized." << std::endl;
11+ }
12+
13+ ~HotkeyManager () {
14+ // Clean up all registered hotkeys
15+ for (const auto & pair : hotkeyCallbacks) {
16+ UnregisterHotKey (nullptr , pair.first );
17+ std::cout << " Unregistered hotkey ID: " << pair.first << std::endl;
18+ }
19+ hotkeyCallbacks.clear ();
20+ }
21+
22+ int registerHotkey (const UINT modifiers, const UINT vk) {
23+ const int currentIdAttempt = nextHotkeyId; // Use a temporary variable for logging before incrementing
24+ if (RegisterHotKey (nullptr , currentIdAttempt, modifiers, vk)) {
25+ nextHotkeyId++; // Increment only on success
26+ std::cout << " Hotkey registered successfully: ID=" << currentIdAttempt
27+ << " , Modifiers=0x" << std::hex << modifiers
28+ << " , VK=0x" << std::hex << vk << std::dec << std::endl;
29+ return currentIdAttempt;
30+ }
31+ DWORD errorCode = GetLastError ();
32+ std::cerr << " Failed to register hotkey: Modifiers=0x" << std::hex << modifiers
33+ << " , VK=0x" << std::hex << vk << std::dec
34+ << " . Error code: " << errorCode << std::endl;
35+ return -1 ;
36+ }
37+
38+ void setCallback (int id, const std::function<void ()>& callback) {
39+ if (id != -1 ) {
40+ hotkeyCallbacks[id] = callback;
41+ std::cout << " Callback set for hotkey ID: " << id << std::endl;
42+ } else {
43+ std::cerr << " Attempted to set callback for invalid hotkey ID (-1)." << std::endl;
44+ }
45+ }
46+
47+ // Processes a given MSG struct. Returns true if it was a hotkey message and handled, false otherwise.
48+ bool processMessage (const MSG& msg) { // Go back to const reference but handle carefully
49+ if (msg.message == WM_HOTKEY) {
50+ // Extract only what we need - the ID
51+ int hotkeyId = static_cast <int >(msg.wParam );
52+
53+ std::cout << " HotkeyManager::processMessage - WM_HOTKEY received. ID: " << hotkeyId << std::endl;
54+
55+ // Find the callback
56+ auto it = hotkeyCallbacks.find (hotkeyId);
57+ if (it != hotkeyCallbacks.end () && it->second ) {
58+ std::cout << " HotkeyManager::processMessage - Executing callback for hotkey ID: " << hotkeyId << std::endl;
59+
60+ // Execute the callback directly - no need for a local copy
61+ it->second ();
62+ } else {
63+ std::cerr << " HotkeyManager::processMessage - No callback found for hotkey ID: " << hotkeyId << std::endl;
64+ }
65+
66+ return true ; // Hotkey message was processed
67+ }
68+
69+ return false ; // Not a hotkey message
70+ }
71+
72+ /*
73+ // The handleHotkeys method with PeekMessage is not suitable when GetMessage is used in the main loop
74+ // as GetMessage will consume the WM_HOTKEY before PeekMessage in this function can see it.
75+ // This function would be more appropriate if HotkeyManager ran its own message loop
76+ // or if PeekMessage was used exclusively in the main loop.
77+ void handleHotkeys() {
78+ MSG msg;
79+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
80+ if (msg.message == WM_HOTKEY) {
81+ int hotkeyId = static_cast<int>(msg.wParam);
82+ std::cout << "WM_HOTKEY received. ID: " << hotkeyId << std::endl;
83+ if (hotkeyCallbacks.count(hotkeyId) > 0) {
84+ std::cout << "Executing callback for hotkey ID: " << hotkeyId << std::endl;
85+ hotkeyCallbacks[hotkeyId]();
86+ } else {
87+ std::cerr << "No callback found for hotkey ID: " << hotkeyId << std::endl;
88+ }
89+ }
90+ }
91+ }
92+ */
93+
94+ private:
95+ int nextHotkeyId;
96+ std::unordered_map<int , std::function<void ()>> hotkeyCallbacks;
97+ };
0 commit comments