#region Thread
private static Thread _hkThread;
private static readonly Queue<Hotkey> PendingRegistrations = new Queue<Hotkey>();
private static readonly Queue<Hotkey> PendingUnregistrations = new Queue<Hotkey>();
private static void EnsureThread()
{
if (_hkThread == null)
{
_hkThread = new Thread(HotkeyThread) { Name = "Hotkey Processing Loop", IsBackground = true };
_hkThread.Start();
}
}
private static void HotkeyThread()
{
while (true)
{
Hotkey[] hotkeysCopy;
lock (_lockObj)
{
while (PendingRegistrations.Count != 0)
{
Hotkey registration = PendingRegistrations.Dequeue();
InternalRegisterHotkey(registration);
}
while (PendingUnregistrations.Count != 0)
{
Hotkey registration = PendingUnregistrations.Dequeue();
InternalUnregisterHotkey(registration);
}
hotkeysCopy = HotkeysList.ToArray();
}
// Ok, so basically, we need to unregister the global hotkeys when the window isn't focused.
// And re-register when it is. This is to avoid blocking other instances of the bot from being able to register the same hotkey.
if (GetForegroundWindow() != _watchhWnd)
{
foreach (Hotkey hk in hotkeysCopy)
{
InternalUnregisterHotkey(hk);
}
}
else
{
// Register hotkeys!
foreach (Hotkey hk in hotkeysCopy)
{
InternalRegisterHotkey(hk);
}
MessagePump();
}
Thread.Sleep(100);
}
}
private static void MessagePump()
{
MSG msg;
// Use PeekMessage as it returns immediately. Doesn't block the calling thread. This means if there are no messages to get,
// we don't block registrations/unregistrations.
while (PeekMessage(out msg, IntPtr.Zero, WM_HOTKEY, WM_HOTKEY, 1))
{
Hotkey pressedHotkey = RegisteredHotkeys.FirstOrDefault(h => h.Id == (int)msg.wParam);
if (pressedHotkey != null)
{
Log.Debug(pressedHotkey.Name + " pressed.");
pressedHotkey.Callback(pressedHotkey);
}
}
}
#endregion