Skip to content

Commit

Permalink
Merge hotkey-fix.
Browse files Browse the repository at this point in the history
  • Loading branch information
aurolou committed Apr 15, 2019
1 parent 843556d commit 2a51f57
Showing 1 changed file with 87 additions and 8 deletions.
95 changes: 87 additions & 8 deletions Frontend/KeyboardHook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,52 @@

namespace Frontend {
class KeyboardHook {
public
struct tagKBDLLHOOKSTRUCT
{
public
int vkCode;
public
int scanCode;
public
int flags;
public
int time;
public
int dwExtraInfo;
};

public
delegate int LowLevelKeyboardProc(int nCode, int wParam, ref tagKBDLLHOOKSTRUCT lParam);

// C++ functions
[DllImport("kernel32.dll")] public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("user32.dll")] static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn,
IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")] static extern int CallNextHookEx(IntPtr hhk, int nCode, int wParam,
tagKBDLLHOOKSTRUCT lParam);
[DllImport("user32.dll")] static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("kernel32.dll")] static extern int GetLastError();
[DllImport("user32.dll")] static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
[DllImport("user32.dll")] static extern bool UnregisterHotKey(IntPtr hWnd, int id);

const int WH_KEYBOARD_LL = 13;
const int HC_ACTION = 0;
const int WM_KEYDOWN = 0x100;
const int WM_SYSKEYDOWN = 0x104;

private
int keyCode_;
IntPtr globalHook_ = IntPtr.Zero;
IntPtr windowHandler_ = IntPtr.Zero;
bool handled_ = false;
private
LowLevelKeyboardProc keyBoardHookProcDelegate_;

public
KeyboardHook() { }
~KeyboardHook() { }
KeyboardHook() { keyBoardHookProcDelegate_ = KeyboardProc; }
~KeyboardHook() { UnHook(); }
public
bool ActivateHook(int newKeyCode, IntPtr handler)
{
Expand All @@ -51,7 +86,7 @@ bool ActivateHook(int newKeyCode, IntPtr handler)
}
}
else {
globalHook_ = handler;
windowHandler_ = handler;
}

return Hook(newKeyCode);
Expand All @@ -60,10 +95,19 @@ bool ActivateHook(int newKeyCode, IntPtr handler)
public
void UnHook()
{
if (globalHook_ != IntPtr.Zero && !UnregisterHotKey(globalHook_, keyCode_))
// first unregister hotkey and then unhook windows hook
if (windowHandler_ != IntPtr.Zero && !UnregisterHotKey(windowHandler_, keyCode_))
{
// window will be invalid if OCAT gets closed
// int error = GetLastError();
// MessageBox.Show("UnregisterHotKey failed " + error.ToString());
}
windowHandler_ = IntPtr.Zero;

if (globalHook_ != IntPtr.Zero && !UnhookWindowsHookEx(globalHook_))
{
int error = GetLastError();
MessageBox.Show("UnregisterHotKey failed " + error.ToString());
MessageBox.Show("UnhookWindowsHookEx failed " + error.ToString());
}

globalHook_ = IntPtr.Zero;
Expand All @@ -72,7 +116,22 @@ void UnHook()
private
bool Hook(int newKeyCode)
{
if (!RegisterHotKey(globalHook_, newKeyCode, 0, newKeyCode))
IntPtr hMod = LoadLibrary("kernel32.dll");
if (hMod == IntPtr.Zero)
{
MessageBox.Show("Load Library failed");
return false;
}

globalHook_ = SetWindowsHookEx(WH_KEYBOARD_LL, keyBoardHookProcDelegate_, hMod, 0);
if (globalHook_ == IntPtr.Zero)
{
int error = GetLastError();
MessageBox.Show("SetWindowsHookEx failed " + error.ToString());
return false;
}

if (!RegisterHotKey(windowHandler_, newKeyCode, 0, newKeyCode))
{
int error = GetLastError();
if (newKeyCode == 0x7B)
Expand All @@ -84,6 +143,9 @@ bool Hook(int newKeyCode)
{
MessageBox.Show("RegisterHotKey failed " + error.ToString());
}
windowHandler_ = IntPtr.Zero;
// TODO: we only want both hooks registered successfully ?
UnhookWindowsHookEx(globalHook_);
globalHook_ = IntPtr.Zero;
return false;
}
Expand All @@ -97,12 +159,29 @@ bool Hook(int newKeyCode)
public
event KeyboardDownEvent HotkeyDownEvent;

public
public
int KeyboardProc(int nCode, int wParam, ref tagKBDLLHOOKSTRUCT lParam)
{
if (nCode == HC_ACTION)
{
if (lParam.vkCode == keyCode_ && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) &&
(HotkeyDownEvent != null))
{
HotkeyDownEvent();
handled_ = true;
}
}
return CallNextHookEx(globalHook_, nCode, wParam, lParam);
}

public
void OnHotKeyEvent(long lParam)
{
if (lParam == keyCode_ && (HotkeyDownEvent != null))
{
HotkeyDownEvent();
if (!handled_)
HotkeyDownEvent();
handled_ = false;
}
}
}
Expand Down

0 comments on commit 2a51f57

Please sign in to comment.