using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Decal.Interop.Input; namespace Decal.DecalInput { [ComVisible(true)] [Guid("F183506A-3664-49D6-8CA4-CFD295F2811D")] [ClassInterface(ClassInterfaceType.None)] [ComSourceInterfaces(typeof(IHotkeyEvents))] [ProgId("DecalInput.Hotkey")] public class HotkeyImpl : IHotkey { private object _tag; private int _vk = -1; private bool _enabled; public event IHotkeyEvents_HotkeyEventHandler Hotkey; public object Tag { get => _tag; set => _tag = value; } public string Key { get { if (_vk == -1) return string.Empty; string name = KeyNames.NameFromVK(_vk); return name != null ? "{" + name + "}" : ((char)_vk).ToString(); } set { string s = value?.ToUpperInvariant(); if (string.IsNullOrEmpty(s)) return; if (s[0] == '{') { int end = s.IndexOf('}'); if (end > 1) { string keyName = s.Substring(1, end - 1); int vk = KeyNames.VKFromName(keyName); if (vk >= 0) _vk = vk; } } else if (s.Length == 1) { _vk = s[0]; } } } public bool Enabled { get => _enabled; set { if (value == _enabled) return; _enabled = value; if (InputServiceImpl.Instance != null) { if (_enabled) InputServiceImpl.Instance.RegisterHotkey(this); else InputServiceImpl.Instance.UnregisterHotkey(this); } } } internal void FireHotkey() { Hotkey?.Invoke((Hotkey)(object)this); } } internal static class KeyNames { private static readonly Dictionary _nameToVK = new Dictionary(StringComparer.OrdinalIgnoreCase) { {"BACKSPACE", 0x08}, {"BS", 0x08}, {"BKSP", 0x08}, {"CAPSLOCK", 0x14}, {"DELETE", 0x2E}, {"DEL", 0x2E}, {"DOWN", 0x28}, {"END", 0x23}, {"ENTER", 0x0D}, {"ESC", 0x1B}, {"HELP", 0x2F}, {"HOME", 0x24}, {"INS", 0x2D}, {"INSERT", 0x2D}, {"LEFT", 0x25}, {"NUMLOCK", 0x90}, {"PGDN", 0x22}, {"PGUP", 0x21}, {"PRTSC", 0x2C}, {"RIGHT", 0x27}, {"SCROLLLOCK", 0x91}, {"TAB", 0x09}, {"UP", 0x26}, {"F1", 0x70}, {"F2", 0x71}, {"F3", 0x72}, {"F4", 0x73}, {"F5", 0x74}, {"F6", 0x75}, {"F7", 0x76}, {"F8", 0x77}, {"F9", 0x78}, {"F10", 0x79}, {"F11", 0x7A}, {"F12", 0x7B}, {"F13", 0x7C}, {"F14", 0x7D}, {"F15", 0x7E}, {"F16", 0x7F}, {"+", 0x6B}, {"SHIFT", 0x10}, {"CTRL", 0x11}, {"ALT", 0x12}, {"LBUTTON", 0x01}, {"RBUTTON", 0x02} }; private static readonly Dictionary _vkToName; static KeyNames() { _vkToName = new Dictionary(); // Build reverse mapping, preferring longer names foreach (var kvp in _nameToVK) { if (!_vkToName.ContainsKey(kvp.Value) || kvp.Key.Length > _vkToName[kvp.Value].Length) _vkToName[kvp.Value] = kvp.Key; } } public static int VKFromName(string name) => _nameToVK.TryGetValue(name, out int vk) ? vk : -1; public static string NameFromVK(int vk) => _vkToName.TryGetValue(vk, out string name) ? name : null; } }