diff --git a/ClipForge/GlobalHotkeyService.cs b/ClipForge/GlobalHotkeyService.cs index d786b51..551cb5e 100644 --- a/ClipForge/GlobalHotkeyService.cs +++ b/ClipForge/GlobalHotkeyService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.InteropServices; using Microsoft.UI.Xaml; @@ -6,39 +6,49 @@ namespace ClipForge { public class GlobalHotkeyService { - // These two lines talk directly to Windows to register/unregister hotkeys [DllImport("user32.dll")] private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); [DllImport("user32.dll")] private static extern bool UnregisterHotKey(IntPtr hWnd, int id); - // This is the ID we'll use to identify our clip hotkey private const int HOTKEY_CLIP = 1; + private const uint MOD_NOREPEAT = 0x4000; // don't fire on key repeat - // Alt key modifier - private const uint MOD_ALT = 0x0001; - - // F9 key - private const uint VK_F9 = 0x78; - - // This is the "event" that fires when the hotkey is pressed public event Action? ClipRequested; private IntPtr _hwnd; + private uint _modifiers; + private uint _vk; - public void Initialize(IntPtr hwnd) + /// Register the clip hotkey. Use settings values (e.g. HotkeyModifiers, HotkeyVirtualKey). + public void Initialize(IntPtr hwnd, uint modifiers, uint vk) { _hwnd = hwnd; - RegisterHotKey(_hwnd, HOTKEY_CLIP, MOD_ALT, VK_F9); + _modifiers = modifiers; + _vk = vk; + TryRegister(); + } + + /// Update the hotkey at runtime (e.g. after user remaps). Unregisters old and registers new. + public bool UpdateHotkey(uint modifiers, uint vk) + { + UnregisterHotKey(_hwnd, HOTKEY_CLIP); + _modifiers = modifiers; + _vk = vk; + return TryRegister(); + } + + private bool TryRegister() + { + uint mod = _modifiers | MOD_NOREPEAT; + return RegisterHotKey(_hwnd, HOTKEY_CLIP, mod, _vk); } public void ProcessHotkey(int id) { if (id == HOTKEY_CLIP) - { ClipRequested?.Invoke(); - } } public void Cleanup() diff --git a/ClipForge/HotkeyHelper.cs b/ClipForge/HotkeyHelper.cs new file mode 100644 index 0000000..f1f50fa --- /dev/null +++ b/ClipForge/HotkeyHelper.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using Windows.System; + +namespace ClipForge +{ + /// Converts between hotkey modifier/vk and display strings. + public static class HotkeyHelper + { + public const uint MOD_ALT = 0x0001; + public const uint MOD_CONTROL = 0x0002; + public const uint MOD_SHIFT = 0x0004; + public const uint MOD_WIN = 0x0008; + public const uint MOD_NOREPEAT = 0x4000; + + private static readonly Dictionary KeyNames = new() + { + { VirtualKey.LeftButton, "LMB" }, + { VirtualKey.RightButton, "RMB" }, + { VirtualKey.Cancel, "Cancel" }, + { VirtualKey.Back, "Backspace" }, + { VirtualKey.Tab, "Tab" }, + { VirtualKey.Clear, "Clear" }, + { VirtualKey.Enter, "Enter" }, + { VirtualKey.Shift, "Shift" }, + { VirtualKey.Control, "Ctrl" }, + { VirtualKey.Menu, "Alt" }, + { VirtualKey.Pause, "Pause" }, + { VirtualKey.CapitalLock, "Caps Lock" }, + { VirtualKey.Kana, "Kana" }, + { VirtualKey.Hangul, "Hangul" }, + { VirtualKey.Junja, "Junja" }, + { VirtualKey.Final, "Final" }, + { VirtualKey.Hanja, "Hanja" }, + { VirtualKey.Kanji, "Kanji" }, + { VirtualKey.Escape, "Escape" }, + { VirtualKey.Convert, "Convert" }, + { VirtualKey.NonConvert, "NonConvert" }, + { VirtualKey.Accept, "Accept" }, + { VirtualKey.ModeChange, "ModeChange" }, + { VirtualKey.Space, "Space" }, + { VirtualKey.PageUp, "PgUp" }, + { VirtualKey.PageDown, "PgDn" }, + { VirtualKey.End, "End" }, + { VirtualKey.Home, "Home" }, + { VirtualKey.Left, "Left" }, + { VirtualKey.Up, "Up" }, + { VirtualKey.Right, "Right" }, + { VirtualKey.Down, "Down" }, + { VirtualKey.Select, "Select" }, + { VirtualKey.Print, "Print" }, + { VirtualKey.Execute, "Execute" }, + { VirtualKey.Snapshot, "Print Screen" }, + { VirtualKey.Insert, "Insert" }, + { VirtualKey.Delete, "Delete" }, + { VirtualKey.Help, "Help" }, + { VirtualKey.Number0, "0" }, + { VirtualKey.Number1, "1" }, + { VirtualKey.Number2, "2" }, + { VirtualKey.Number3, "3" }, + { VirtualKey.Number4, "4" }, + { VirtualKey.Number5, "5" }, + { VirtualKey.Number6, "6" }, + { VirtualKey.Number7, "7" }, + { VirtualKey.Number8, "8" }, + { VirtualKey.Number9, "9" }, + { VirtualKey.A, "A" }, + { VirtualKey.B, "B" }, + { VirtualKey.C, "C" }, + { VirtualKey.D, "D" }, + { VirtualKey.E, "E" }, + { VirtualKey.F, "F" }, + { VirtualKey.G, "G" }, + { VirtualKey.H, "H" }, + { VirtualKey.I, "I" }, + { VirtualKey.J, "J" }, + { VirtualKey.K, "K" }, + { VirtualKey.L, "L" }, + { VirtualKey.M, "M" }, + { VirtualKey.N, "N" }, + { VirtualKey.O, "O" }, + { VirtualKey.P, "P" }, + { VirtualKey.Q, "Q" }, + { VirtualKey.R, "R" }, + { VirtualKey.S, "S" }, + { VirtualKey.T, "T" }, + { VirtualKey.U, "U" }, + { VirtualKey.V, "V" }, + { VirtualKey.W, "W" }, + { VirtualKey.X, "X" }, + { VirtualKey.Y, "Y" }, + { VirtualKey.Z, "Z" }, + { VirtualKey.LeftWindows, "Win" }, + { VirtualKey.RightWindows, "Win" }, + { VirtualKey.Application, "App" }, + { VirtualKey.Sleep, "Sleep" }, + { VirtualKey.NumberPad0, "Num 0" }, + { VirtualKey.NumberPad1, "Num 1" }, + { VirtualKey.NumberPad2, "Num 2" }, + { VirtualKey.NumberPad3, "Num 3" }, + { VirtualKey.NumberPad4, "Num 4" }, + { VirtualKey.NumberPad5, "Num 5" }, + { VirtualKey.NumberPad6, "Num 6" }, + { VirtualKey.NumberPad7, "Num 7" }, + { VirtualKey.NumberPad8, "Num 8" }, + { VirtualKey.NumberPad9, "Num 9" }, + { VirtualKey.Multiply, "Num *" }, + { VirtualKey.Add, "Num +" }, + { VirtualKey.Separator, "Num ," }, + { VirtualKey.Subtract, "Num -" }, + { VirtualKey.Decimal, "Num ." }, + { VirtualKey.Divide, "Num /" }, + { VirtualKey.F1, "F1" }, + { VirtualKey.F2, "F2" }, + { VirtualKey.F3, "F3" }, + { VirtualKey.F4, "F4" }, + { VirtualKey.F5, "F5" }, + { VirtualKey.F6, "F6" }, + { VirtualKey.F7, "F7" }, + { VirtualKey.F8, "F8" }, + { VirtualKey.F9, "F9" }, + { VirtualKey.F10, "F10" }, + { VirtualKey.F11, "F11" }, + { VirtualKey.F12, "F12" }, + { VirtualKey.F13, "F13" }, + { VirtualKey.F14, "F14" }, + { VirtualKey.F15, "F15" }, + { VirtualKey.F16, "F16" }, + { VirtualKey.F17, "F17" }, + { VirtualKey.F18, "F18" }, + { VirtualKey.F19, "F19" }, + { VirtualKey.F20, "F20" }, + { VirtualKey.F21, "F21" }, + { VirtualKey.F22, "F22" }, + { VirtualKey.F23, "F23" }, + { VirtualKey.F24, "F24" }, + { VirtualKey.NumberKeyLock, "NumLock" }, + { VirtualKey.Scroll, "Scroll Lock" }, + { VirtualKey.LeftShift, "Shift" }, + { VirtualKey.RightShift, "Shift" }, + { VirtualKey.LeftControl, "Ctrl" }, + { VirtualKey.RightControl, "Ctrl" }, + { VirtualKey.LeftMenu, "Alt" }, + { VirtualKey.RightMenu, "Alt" }, + }; + + /// Format modifier flags + virtual key as display string (e.g. "Alt + PgUp"). + public static string ToDisplayString(uint modifiers, uint vk) + { + var parts = new List(); + if ((modifiers & MOD_WIN) != 0) parts.Add("Win"); + if ((modifiers & MOD_CONTROL) != 0) parts.Add("Ctrl"); + if ((modifiers & MOD_ALT) != 0) parts.Add("Alt"); + if ((modifiers & MOD_SHIFT) != 0) parts.Add("Shift"); + var keyName = GetKeyName((VirtualKey)vk); + if (!string.IsNullOrEmpty(keyName)) + parts.Add(keyName); + return parts.Count > 0 ? string.Join(" + ", parts) : "None"; + } + + public static string GetKeyName(VirtualKey key) + { + return KeyNames.TryGetValue(key, out var name) ? name : key.ToString(); + } + + /// True if the key is typically used only as a modifier (don't use as sole key). + public static bool IsModifierKey(VirtualKey key) + { + return key == VirtualKey.LeftWindows || key == VirtualKey.RightWindows + || key == VirtualKey.Control || key == VirtualKey.LeftControl || key == VirtualKey.RightControl + || key == VirtualKey.Menu || key == VirtualKey.LeftMenu || key == VirtualKey.RightMenu + || key == VirtualKey.Shift || key == VirtualKey.LeftShift || key == VirtualKey.RightShift; + } + } +} diff --git a/ClipForge/SettingsService.cs b/ClipForge/SettingsService.cs index 929eb3c..080aeea 100644 --- a/ClipForge/SettingsService.cs +++ b/ClipForge/SettingsService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Text.Json; @@ -9,7 +9,10 @@ namespace ClipForge public int ClipLengthSeconds { get; set; } = 30; public int VideoQuality { get; set; } = 70; public int Framerate { get; set; } = 60; - public string HotkeyDisplay { get; set; } = "Alt + F9"; + /// Windows modifier flags: Alt=1, Ctrl=2, Shift=4, Win=8. + public int HotkeyModifiers { get; set; } = 1; // MOD_ALT + /// Windows virtual key code (e.g. VK_F9=0x78, VK_PRIOR=0x21 for PgUp). + public int HotkeyVirtualKey { get; set; } = 0x78; // VK_F9 } public class SettingsService