XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

LogiBoardToolBox

【WinUI】罗技鼠标板载驱动程序

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Globalization;

namespace LogiBoardToolBox.Core.Macros;

public static class HidKeys
{
    private static readonly Dictionary<string, byte> Keys = new(StringComparer.OrdinalIgnoreCase)
    {
        ["Enter"] = 0x28, ["Escape"] = 0x29, ["Esc"] = 0x29, ["Backspace"] = 0x2A,
        ["Tab"] = 0x2B, ["Space"] = 0x2C, ["Minus"] = 0x2D, ["Equal"] = 0x2E,
        ["LeftBracket"] = 0x2F, ["RightBracket"] = 0x30, ["Backslash"] = 0x31,
        ["Semicolon"] = 0x33, ["Quote"] = 0x34, ["Grave"] = 0x35,
        ["Comma"] = 0x36, ["Period"] = 0x37, ["Slash"] = 0x38, ["CapsLock"] = 0x39,
        ["PrintScreen"] = 0x46, ["ScrollLock"] = 0x47, ["Pause"] = 0x48,
        ["Insert"] = 0x49, ["Home"] = 0x4A, ["PageUp"] = 0x4B, ["Delete"] = 0x4C,
        ["End"] = 0x4D, ["PageDown"] = 0x4E, ["Right"] = 0x4F, ["Left"] = 0x50,
        ["Down"] = 0x51, ["Up"] = 0x52, ["NumLock"] = 0x53,
        ["NumpadDivide"] = 0x54, ["NumpadMultiply"] = 0x55, ["NumpadSubtract"] = 0x56,
        ["NumpadAdd"] = 0x57, ["NumpadEnter"] = 0x58, ["Numpad0"] = 0x62,
        ["NumpadDecimal"] = 0x63, ["Menu"] = 0x65
    };
    private static readonly Dictionary<string, byte> Modifiers = new(StringComparer.OrdinalIgnoreCase)
    {
        ["Ctrl"] = 1, ["Control"] = 1, ["LeftCtrl"] = 1, ["Shift"] = 2, ["LeftShift"] = 2,
        ["Alt"] = 4, ["LeftAlt"] = 4, ["Win"] = 8, ["Meta"] = 8, ["LeftWin"] = 8,
        ["RightCtrl"] = 16, ["RightShift"] = 32, ["RightAlt"] = 64, ["RightWin"] = 128
    };
    static HidKeys()
    {
        for (var i = 0; i < 26; i++) Keys[((char)('A' + i)).ToString()] = (byte)(4 + i);
        for (var i = 1; i <= 9; i++) { Keys[i.ToString()] = (byte)(0x1D + i); Keys[$"Numpad{i}"] = (byte)(0x58 + i); }
        Keys["0"] = 0x27;
        for (var i = 1; i <= 12; i++) Keys[$"F{i}"] = (byte)(0x39 + i);
        for (var i = 13; i <= 24; i++) Keys[$"F{i}"] = (byte)(0x68 + i - 13);
    }

    public static (byte Modifier, byte Usage) ParseChord(string text)
    {
        byte modifier = 0, usage = 0;
        var parts = text.Split('+', StringSplitOptions.TrimEntries);
        if (parts.Any(string.IsNullOrWhiteSpace)) throw new FormatException("快捷键不能为空,例如 Ctrl+Shift+A。");
        foreach (var part in parts)
        {
            if (Modifiers.TryGetValue(part, out var mask)) modifier |= mask;
            else
            {
                if (usage != 0) throw new FormatException("一个快捷键只能包含一个普通键;多个键请使用宏。");
                if (!Keys.TryGetValue(part, out usage))
                {
                    if (!part.StartsWith("0x", StringComparison.OrdinalIgnoreCase) || !byte.TryParse(part.AsSpan(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out usage) || usage == 0)
                        throw new FormatException($"未知键名 {part}。也可使用 HID 十六进制键码,例如 0x04。");
                }
                if (usage is >= 0xE0 and <= 0xE7) { modifier |= (byte)(1 << (usage - 0xE0)); usage = 0; }
            }
        }
        if (modifier == 0 && usage == 0) throw new FormatException("快捷键不能为空。");
        return (modifier, usage);
    }

    public static string Describe(byte modifier, byte usage)
    {
        string[] names = ["Ctrl", "Shift", "Alt", "Win", "RightCtrl", "RightShift", "RightAlt", "RightWin"];
        var parts = Enumerable.Range(0, 8).Where(i => (modifier & (1 << i)) != 0).Select(i => names[i]).ToList();
        if (usage != 0) parts.Add(Keys.FirstOrDefault(k => k.Value == usage).Key ?? $"0x{usage:X2}");
        return string.Join('+', parts);
    }
}