-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
YAMDCC hotkey handler: initial version
Currently the only hotkey supported is the MSI Center key (which opens the YAMDCC config editor by default, and will be configurable). Please test and report if the MSI Center key isn't working with Hotkey Handler.
- Loading branch information
1 parent
ba29372
commit 6e4fb21
Showing
12 changed files
with
1,362 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<configuration> | ||
<System.Windows.Forms.ApplicationConfigurationSection> | ||
<add key="DpiAwareness" value="PerMonitorV2"/> | ||
<add key="EnableWindowsFormsHighDpiAutoResizing" value="true"/> | ||
</System.Windows.Forms.ApplicationConfigurationSection> | ||
<startup> | ||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /> | ||
</startup> | ||
</configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Runtime.InteropServices; | ||
using System.Windows.Forms; | ||
using YAMDCC.HotkeyHandler.Win32; | ||
|
||
namespace YAMDCC.HotkeyHandler; | ||
|
||
internal class KeyHook : IDisposable | ||
{ | ||
private readonly HookProc KbdHookProc; | ||
private IntPtr KbdHookPtr; | ||
|
||
/// <summary> | ||
/// Used to determine if we should raise the <see cref="KeyDown"/> | ||
/// event when <see cref="IgnoreRepeats"/> is <see langword="true"/>. | ||
/// </summary> | ||
private readonly HashSet<uint> HeldKeys = []; | ||
|
||
/// <summary> | ||
/// Gets or sets whether to raise <see cref="KeyDown"/> events when | ||
/// a key press is automatically repeated due to the key being held down. | ||
/// </summary> | ||
public bool IgnoreRepeats { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets whether to raise <see cref="KeyDown"/> or <see cref="KeyUp"/> | ||
/// events when a modifier key (Ctrl, Shift, or Alt) is pressed. | ||
/// </summary> | ||
public bool IgnoreModifiers { get; set; } | ||
|
||
/// <summary> | ||
/// Gets the currently held modifier keys. | ||
/// </summary> | ||
public ConsoleModifiers Modifiers { get; private set; } | ||
|
||
/// <summary> | ||
/// Occurs when a key is pressed. | ||
/// </summary> | ||
public event EventHandler<KeyHookEventArgs> KeyDown; | ||
|
||
/// <summary> | ||
/// Occurs when a key is released. | ||
/// </summary> | ||
public event EventHandler<KeyHookEventArgs> KeyUp; | ||
|
||
public KeyHook(bool ignoreRepeats = true, bool ignoreModifiers = false) | ||
{ | ||
KbdHookProc = new HookProc(HookProcCallback); | ||
IgnoreRepeats = ignoreRepeats; | ||
IgnoreModifiers = ignoreModifiers; | ||
} | ||
|
||
/// <summary> | ||
/// Uninstalls the keyboard hook and releases all unmanaged | ||
/// resources associated with this <see cref="KeyHook"/> instance. | ||
/// </summary> | ||
public void Dispose() | ||
{ | ||
Uninstall(); | ||
GC.SuppressFinalize(this); | ||
} | ||
|
||
~KeyHook() | ||
{ | ||
Uninstall(); | ||
} | ||
|
||
public bool Install() | ||
{ | ||
if (KbdHookPtr == IntPtr.Zero) | ||
{ | ||
KbdHookPtr = User32.SetWindowsHookEx(13, KbdHookProc, | ||
Marshal.GetHINSTANCE(typeof(KeyHook).Module), 0); | ||
return KbdHookPtr != IntPtr.Zero; | ||
} | ||
// keyboard hook already installed | ||
return true; | ||
} | ||
|
||
public bool Uninstall() | ||
{ | ||
// uninstall keyboard hook if installed (KbdHookPtr != IntPtr.Zero), | ||
// otherwise just return true | ||
return KbdHookPtr == IntPtr.Zero || User32.UnhookWindowsHookEx(KbdHookPtr); | ||
} | ||
|
||
private IntPtr HookProcCallback(int nCode, IntPtr wParam, IntPtr lParam) | ||
{ | ||
if (nCode >= 0 && wParam.ToInt32() is 0x100 or 0x101 or 0x104 or 0x105) | ||
{ | ||
KbdLLHookStruct kbdStruct = Marshal.PtrToStructure<KbdLLHookStruct>(lParam); | ||
KeyHookEventArgs e = new( | ||
kbdStruct.KeyCode, | ||
kbdStruct.ScanCode, | ||
(kbdStruct.Flags & 0x01) == 1, | ||
(kbdStruct.Flags & 0x02) == 1, | ||
(kbdStruct.Flags & 0x10) == 1); | ||
|
||
switch (wParam.ToInt32()) | ||
{ | ||
case 0x100: // WM_KEYDOWN | ||
case 0x104: // WM_SYSKEYDOWN | ||
if (HandleModifiers(e.KeyCode, true) && | ||
(!IgnoreRepeats || !HeldKeys.Contains(e.ScanCode))) | ||
{ | ||
KeyDown?.Invoke(this, e); | ||
} | ||
HeldKeys.Add(e.ScanCode); | ||
break; | ||
case 0x101: // WM_KEYUP | ||
case 0x105: // WM_SYSKEYUP | ||
if (HandleModifiers(e.KeyCode, false)) | ||
{ | ||
KeyUp?.Invoke(this, e); | ||
} | ||
HeldKeys.Remove(e.ScanCode); | ||
break; | ||
} | ||
|
||
if (e.SuppressKeyPress) | ||
{ | ||
return new IntPtr(1); | ||
} | ||
} | ||
return User32.CallNextHookEx(KbdHookPtr, nCode, wParam, lParam); | ||
} | ||
|
||
private bool HandleModifiers(Keys key, bool pressed) | ||
{ | ||
ConsoleModifiers modifier; | ||
switch (key) | ||
{ | ||
case Keys.LMenu: | ||
case Keys.RMenu: | ||
modifier = ConsoleModifiers.Alt; | ||
break; | ||
case Keys.LShiftKey: | ||
case Keys.RShiftKey: | ||
modifier = ConsoleModifiers.Shift; | ||
break; | ||
case Keys.LControlKey: | ||
case Keys.RControlKey: | ||
modifier = ConsoleModifiers.Control; | ||
break; | ||
default: | ||
return true; | ||
} | ||
|
||
if (pressed) | ||
{ | ||
Modifiers |= modifier; | ||
} | ||
else | ||
{ | ||
Modifiers &= ~modifier; | ||
} | ||
return !IgnoreModifiers; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System; | ||
using System.Windows.Forms; | ||
|
||
namespace YAMDCC.HotkeyHandler; | ||
|
||
internal class KeyHookEventArgs : EventArgs | ||
{ | ||
public Keys KeyCode { get; } | ||
public uint ScanCode { get; } | ||
public bool ExtendedKey { get; } | ||
public bool LowerILInjected { get; } | ||
public bool Injected { get; } | ||
|
||
/// <summary> | ||
/// Gets or sets a value indicating whether the | ||
/// key event should be sent to other applications. | ||
/// </summary> | ||
/// <returns> | ||
/// <see langword="true"/> if the key event should not be sent | ||
/// to other applications, otherwise <see langword="false"/>. | ||
/// </returns> | ||
public bool SuppressKeyPress { get; set; } | ||
|
||
/// <summary> | ||
/// Initialises a new instance of the <see cref="KeyHookEventArgs"/> class. | ||
/// </summary> | ||
/// <param name="keyCode"></param> | ||
/// <param name="scanCode"></param> | ||
/// <param name="extendedKey"></param> | ||
/// <param name="lowerILInjected"></param> | ||
/// <param name="injected"></param> | ||
public KeyHookEventArgs(Keys keyCode, uint scanCode, bool extendedKey, bool lowerILInjected, bool injected) | ||
{ | ||
KeyCode = keyCode; | ||
ScanCode = scanCode; | ||
ExtendedKey = extendedKey; | ||
LowerILInjected = lowerILInjected; | ||
Injected = injected; | ||
} | ||
} |
Oops, something went wrong.
6e4fb21
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems doesent work for my gf66 12UG, i tried fn+f7 combo (switch msi center profiles)
6e4fb21
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That key combo should open the YAMDCC config editor as long as Hotkey Handler is running (assuming the key combo is the same on your laptop, see the next paragraph).
On my laptop, the F7 key has a "G" symbol on it that opens MSI Center (if installed). Try looking for a similar key on your laptop.
If the key combo is indeed Fn+F7 like on my laptop, the hardware scan codes might differ between MSI laptops.
I will update Hotkey Handler Soon™ with functionality to view detected key presses.