using CommunityToolkit.Mvvm.ComponentModel; using System; using System.Windows.Forms; using System.Windows.Input; using Windows.Networking.PushNotifications; using static Vanara.PInvoke.User32; namespace BetterGenshinImpact.Core.Config; /// /// 原神按键绑定配置 /// [Serializable] public partial class KeyBindingsConfig:ObservableObject { /// /// 是否启用全局按键映射 /// [ObservableProperty] private bool _globalKeyMappingEnabled = false; #region Actions(操作) /// /// 向前移动 /// [ObservableProperty] private KeyId _moveForward = KeyId.W; /// /// 向后移动 /// [ObservableProperty] private KeyId _moveBackward = KeyId.S; /// /// 向左移动 /// [ObservableProperty] private KeyId _moveLeft = KeyId.A; /// /// 向右移动 /// [ObservableProperty] private KeyId _moveRight = KeyId.D; /// /// 切换走/跑;特定操作模式下向下移动 /// [ObservableProperty] private KeyId _switchToWalkOrRun = KeyId.LeftCtrl; /// /// 普通攻击 /// [ObservableProperty] private KeyId _normalAttack = KeyId.MouseLeftButton; /// /// 元素战技 /// [ObservableProperty] private KeyId _elementalSkill = KeyId.E; /// /// 元素爆发 /// [ObservableProperty] private KeyId _elementalBurst = KeyId.Q; /// /// 冲刺(键盘) /// [ObservableProperty] private KeyId _sprintKeyboard = KeyId.LeftShift; /// /// 冲刺(鼠标) /// [ObservableProperty] private KeyId _sprintMouse = KeyId.MouseRightButton; /// /// 切换瞄准模式 /// [ObservableProperty] private KeyId _switchAimingMode = KeyId.R; /// /// 跳跃;特定操作模式下向上移动 /// [ObservableProperty] private KeyId _jump = KeyId.Space; /// /// 落下 /// [ObservableProperty] private KeyId _drop = KeyId.X; /// /// 拾取/交互(自动拾取由AutoPick模块管理) /// [ObservableProperty] private KeyId _pickUpOrInteract = KeyId.F; /// /// 快捷使用小道具 /// [ObservableProperty] private KeyId _quickUseGadget = KeyId.Z; /// /// 特定玩法内交互操作 /// [ObservableProperty] private KeyId _interactionInSomeMode = KeyId.T; /// /// 开启任务追踪 /// [ObservableProperty] private KeyId _questNavigation = KeyId.V; /// /// 中断挑战 /// [ObservableProperty] private KeyId _abandonChallenge = KeyId.P; /// /// 切换小队角色1 /// [ObservableProperty] private KeyId _switchMember1 = KeyId.D1; /// /// 切换小队角色2 /// [ObservableProperty] private KeyId _switchMember2 = KeyId.D2; /// /// 切换小队角色3 /// [ObservableProperty] private KeyId _switchMember3 = KeyId.D3; /// /// 切换小队角色4 /// [ObservableProperty] private KeyId _switchMember4 = KeyId.D4; /// /// 切换小队角色5 /// [ObservableProperty] private KeyId _switchMember5 = KeyId.D5; /// /// 呼出快捷轮盘 /// [ObservableProperty] private KeyId _shortcutWheel = KeyId.Tab; #endregion #region Menus(菜单) /// /// 打开背包 /// [ObservableProperty] private KeyId _openInventory = KeyId.B; /// /// 打开角色界面 /// [ObservableProperty] private KeyId _openCharacterScreen = KeyId.C; /// /// 打开地图 /// [ObservableProperty] private KeyId _openMap = KeyId.M; /// /// 打开派蒙界面 /// [ObservableProperty] private KeyId _openPaimonMenu = KeyId.Escape; /// /// 打开冒险之证界面 /// [ObservableProperty] private KeyId _openAdventurerHandbook = KeyId.F1; /// /// 打开多人游戏界面 /// [ObservableProperty] private KeyId _openCoOpScreen = KeyId.F2; /// /// 打开祈愿界面 /// [ObservableProperty] private KeyId _openWishScreen = KeyId.F3; /// /// 打开纪行界面 /// [ObservableProperty] private KeyId _openBattlePassScreen = KeyId.F4; /// /// 打开活动面板 /// [ObservableProperty] private KeyId _openTheEventsMenu = KeyId.F5; /// /// 打开玩法系统界面(尘歌壶内猫尾酒馆内) /// [ObservableProperty] private KeyId _openTheSettingsMenu = KeyId.F6; /// /// 打开摆设界面(尘歌壶内) /// [ObservableProperty] private KeyId _openTheFurnishingScreen = KeyId.F7; /// /// 打开星之归还(条件符合期间生效) /// [ObservableProperty] private KeyId _openStellarReunion = KeyId.F8; /// /// 开关任务菜单 /// [ObservableProperty] private KeyId _openQuestMenu = KeyId.J; /// /// 打开通知详情 /// [ObservableProperty] private KeyId _openNotificationDetails = KeyId.Y; /// /// 打开聊天界面 /// [ObservableProperty] private KeyId _openChatScreen = KeyId.Enter; /// /// 打开特殊环境说明 /// [ObservableProperty] private KeyId _openSpecialEnvironmentInformation = KeyId.U; /// /// 查看教程详情 /// [ObservableProperty] private KeyId _checkTutorialDetails = KeyId.G; /// /// 长按打开元素视野 /// [ObservableProperty] private KeyId _elementalSight = KeyId.MouseMiddleButton; /// /// 呼出鼠标 /// [ObservableProperty] private KeyId _showCursor = KeyId.LeftAlt; /// /// 打开队伍配置界面 /// [ObservableProperty] private KeyId _openPartySetupScreen = KeyId.L; /// /// 打开好友界面 /// [ObservableProperty] private KeyId _openFriendsScreen = KeyId.O; /// /// 隐藏主界面 /// [ObservableProperty] private KeyId _hideUI = KeyId.Slash; #endregion } public static class KeyIdConverter { /// /// 将KeyId转换为字符串(可在后续支持多语言),按键名称的显示尽量与原神UI一致 /// /// /// public static string ToName(this KeyId value) { return ToChineseName(value); } private static string ToChineseName(KeyId value) { return value switch { // 需要单独翻译的按键 KeyId.None => "<未指定>", KeyId.Unknown => "<未知>", KeyId.MouseLeftButton => "鼠标左键", KeyId.MouseRightButton => "鼠标右键", KeyId.MouseMiddleButton => "鼠标中键", KeyId.MouseSideButton1 => "鼠标侧键1", KeyId.MouseSideButton2 => "鼠标侧键2", KeyId.Apps => "菜单键", // 无需单独翻译的部分 _ => EnglishKeyNameToChinese(value), }; } private static string EnglishKeyNameToChinese(KeyId value) { var engName = ToEnglishName(value); if (engName.StartsWith("Left ") || engName.StartsWith("Right ")) { return engName.Replace("Left ", "左").Replace("Right ", "右"); } return engName; } private static string ToEnglishName(KeyId value) { return value switch { // 需要转换的部分 KeyId.None => "", KeyId.Unknown => "", KeyId.MouseLeftButton => "Mouse LButton", KeyId.MouseRightButton => "Mouse RButton", KeyId.MouseMiddleButton => "Mouse MButton", KeyId.MouseSideButton1 => "Mouse XButton1", KeyId.MouseSideButton2 => "Mouse XButton2", KeyId.Escape => "Esc", KeyId.PageUp => "Page Up", KeyId.PageDown => "Page Down", KeyId.CapsLock => "Caps Lock", KeyId.ScrollLock => "Scroll Lock", KeyId.LeftShift => "Left Shift", KeyId.RightShift => "Right Shift", KeyId.LeftCtrl => "Left Ctrl", KeyId.RightCtrl => "Right Ctrl", KeyId.LeftAlt => "Left Alt", KeyId.RightAlt => "Right Alt", KeyId.LeftWin => "Left Win", KeyId.RightWin => "Right Win", KeyId.Apps => "Menu", KeyId.Left => "←", KeyId.Up => "↑", KeyId.Right => "→", KeyId.Down => "↓", KeyId.D0 => "0", KeyId.D1 => "1", KeyId.D2 => "2", KeyId.D3 => "3", KeyId.D4 => "4", KeyId.D5 => "5", KeyId.D6 => "6", KeyId.D7 => "7", KeyId.D8 => "8", KeyId.D9 => "9", KeyId.Apostrophe => "'", KeyId.Comma => ",", KeyId.Minus => "-", KeyId.Equal => "=", KeyId.Period => ".", KeyId.Slash => "/", KeyId.Backslash => @"\", KeyId.Semicolon => ";", KeyId.LeftSquareBracket => "[", KeyId.RightSquareBracket => "]", KeyId.Tilde => "`", KeyId.NumLock => "Num Lock", KeyId.NumPad0 => "Num 0", KeyId.NumPad1 => "Num 1", KeyId.NumPad2 => "Num 2", KeyId.NumPad3 => "Num 3", KeyId.NumPad4 => "Num 4", KeyId.NumPad5 => "Num 5", KeyId.NumPad6 => "Num 6", KeyId.NumPad7 => "Num 7", KeyId.NumPad8 => "Num 8", KeyId.NumPad9 => "Num 9", KeyId.Decimal => "Num .", KeyId.Divide => "Num /", KeyId.Multiply => "Num *", KeyId.Subtract => "Num -", KeyId.Add => "Num +", KeyId.NumEnter => "Num Enter", // 默认使用枚举名 _ => value.ToString(), }; } /// /// 将KeyId转换为VK /// /// /// public static VK ToVK(this KeyId value) { return value switch { // 这两个值在VK中没有,抛异常 KeyId.None => throw new ArgumentOutOfRangeException(nameof(value), "未指定按键,无法转换为VK。"), KeyId.Unknown => throw new ArgumentOutOfRangeException(nameof(value), "未知按键,无法转换为VK。"), // 剩下的值相同,直接转 _ => (VK)value, }; } /// /// 将KeyId转换为System.Windows.Input.Key /// /// /// public static Key ToInputKey(this KeyId value) { // 部分按键名称相同,使用名称转换 try { return Enum.Parse(value.ToString()); } catch { // 其他键使用查表法转换 return value switch { KeyId.LeftWin => Key.LWin, KeyId.RightWin => Key.RWin, KeyId.Apostrophe => Key.Oem7, KeyId.Comma => Key.OemComma, KeyId.Minus => Key.OemMinus, KeyId.Equal => Key.OemPlus, KeyId.Period => Key.OemPeriod, KeyId.Slash => Key.Oem2, KeyId.Semicolon => Key.Oem1, KeyId.LeftSquareBracket => Key.Oem4, KeyId.Backslash => Key.Oem5, KeyId.RightSquareBracket => Key.Oem6, KeyId.Tilde => Key.Oem3, KeyId.Enter => Key.Enter, KeyId.ScrollLock => Key.Scroll, KeyId.PageUp => Key.Prior, KeyId.PageDown => Key.Next, KeyId.Backspace => Key.Back, KeyId.CapsLock => Key.Capital, // None、Unknown和鼠标按键抛异常 _ => throw new ArgumentOutOfRangeException(nameof(value)), }; } } /// /// 将KeyId转换为MouseButton /// /// /// /// public static MouseButton ToMouseButton(this KeyId value) { return value switch { KeyId.MouseLeftButton => MouseButton.Left, KeyId.MouseRightButton => MouseButton.Right, KeyId.MouseMiddleButton => MouseButton.Middle, KeyId.MouseSideButton1 => MouseButton.XButton1, KeyId.MouseSideButton2 => MouseButton.XButton2, _ => throw new ArgumentOutOfRangeException(nameof(value), "键盘按键请使用ToInputKey方法"), }; } /// /// [实验] 将KeyId转换为WinForm中的Keys(用于兼容按键连发功能) /// /// /// public static Keys ToWinFormKeys(this KeyId value) { try { return Enum.Parse(value.ToInputKey().ToString()); } catch { return default; } } /// /// 将VK转换为KeyId /// /// /// public static KeyId FromVK(VK value) { // 尝试通过VK的值获取KeyId的枚举名。若成功,表示对应的VK在KeyId支持的范围内,直接转换;否则返回Unknown return string.IsNullOrEmpty(Enum.GetName(typeof(KeyId), value)) ? KeyId.Unknown : (KeyId)value; } /// /// 将System.Windows.Input.Key转换为KeyId /// /// /// public static KeyId FromInputKey(Key value) { // 部分按键名称相同,使用名称转换 try { return Enum.Parse(value.ToString()); } catch { // 其他键使用查表法转换 return value switch { Key.LWin => KeyId.LeftWin, Key.RWin => KeyId.RightWin, Key.Oem7 => KeyId.Apostrophe, Key.OemComma => KeyId.Comma, Key.OemMinus => KeyId.Minus, Key.OemPlus => KeyId.Equal, Key.OemPeriod => KeyId.Period, Key.Oem2 => KeyId.Slash, Key.Oem1 => KeyId.Semicolon, Key.Oem4 => KeyId.LeftSquareBracket, Key.Oem5 => KeyId.Backslash, Key.Oem6 => KeyId.RightSquareBracket, Key.Oem3 => KeyId.Tilde, Key.Enter => KeyId.Enter, Key.Scroll => KeyId.ScrollLock, Key.Prior => KeyId.PageUp, Key.Next => KeyId.PageDown, Key.Back => KeyId.Backspace, Key.Capital => KeyId.CapsLock, // 支持列表外的值返回Unknown _ => KeyId.Unknown, }; } } /// /// 将MouseButton转换为KeyId /// /// /// public static KeyId FromMouseButton(MouseButton value) { return value switch { MouseButton.Left => KeyId.MouseLeftButton, MouseButton.Right => KeyId.MouseRightButton, MouseButton.Middle => KeyId.MouseMiddleButton, MouseButton.XButton1 => KeyId.MouseSideButton1, MouseButton.XButton2 => KeyId.MouseSideButton2, _ => KeyId.Unknown, }; } } /// /// 用于与VK/Windows.Input.Key解耦,值与VK对应,但是仅包含美式键盘(104键,不包括媒体控制等)和鼠标中的按键 /// public enum KeyId { /// None = 0x00, /// 未知按键 Unknown = 0xFF, #region 鼠标按键 /// 鼠标左键 MouseLeftButton = 0x01, /// 鼠标右键 MouseRightButton = 0x02, /// 鼠标中键(滚轮) MouseMiddleButton = 0x04, /// 鼠标侧键1(后退) MouseSideButton1 = 0x05, /// 鼠标侧键2(前进) MouseSideButton2 = 0x06, #endregion #region F键区 /// F1 F1 = 0x70, /// F2 F2 = 0x71, /// F3 F3 = 0x72, /// F4 F4 = 0x73, /// F5 F5 = 0x74, /// F6 F6 = 0x75, /// F7 F7 = 0x76, /// F8 F8 = 0x77, /// F9 F9 = 0x78, /// F10 F10 = 0x79, /// F11 F11 = 0x7A, /// F12 F12 = 0x7B, #endregion #region 控制&功能键 /// Esc Escape = 0x1B, /// PrintScreen PrintScreen = 0x2C, /// ScrollLock ScrollLock = 0x91, /// Pause Pause = 0x13, /// Insert Insert = 0x2D, /// Delete Delete = 0x2E, /// Home Home = 0x24, /// End End = 0x23, /// Page Up PageUp = 0x21, /// Page Down PageDown = 0x22, /// Backspace退格 Backspace = 0x08, /// Tab Tab = 0x09, /// Caps Lock大写锁定 CapsLock = 0x14, /// Enter回车 Enter = 0x0D, ///// Shift //Shift = 0x10, /// 左Shift LeftShift = 0xA0, /// 右Shift RightShift = 0xA1, ///// Ctrl //Ctrl = 0x11, /// 左Ctrl LeftCtrl = 0xA2, /// 右Ctrl RightCtrl = 0xA3, ///// Alt //Alt = 0x12, /// 左Alt LeftAlt = 0xA4, /// 右Alt RightAlt = 0xA5, /// 左Win键 (Microsoft Natural Keyboard) LeftWin = 0x5B, /// 右Win键 (Microsoft Natural Keyboard) RightWin = 0x5C, /// 菜单键 (Microsoft Natural Keyboard) Apps = 0x5D, /// Space空格键 Space = 0x20, #endregion #region 方向键 /// 方向键 ← Left = 0x25, /// 方向键 ↑ Up = 0x26, /// 方向键 → Right = 0x27, /// 方向键 ↓ Down = 0x28, #endregion #region 字母区 - 字母 /// A A = 0x41, /// B B = 0x42, /// C C = 0x43, /// D D = 0x44, /// E E = 0x45, /// F F = 0x46, /// G G = 0x47, /// H H = 0x48, /// I I = 0x49, /// J J = 0x4A, /// K K = 0x4B, /// L L = 0x4C, /// M M = 0x4D, /// N N = 0x4E, /// O O = 0x4F, /// P P = 0x50, /// Q Q = 0x51, /// R R = 0x52, /// S S = 0x53, /// T T = 0x54, /// U U = 0x55, /// V V = 0x56, /// W W = 0x57, /// X X = 0x58, /// Y Y = 0x59, /// Z Z = 0x5A, #endregion #region 字母区 - 数字 /// 0 D0 = 0x30, /// 1 D1 = 0x31, /// 2 D2 = 0x32, /// 3 D3 = 0x33, /// 4 D4 = 0x34, /// 5 D5 = 0x35, /// 6 D6 = 0x36, /// 7 D7 = 0x37, /// 8 D8 = 0x38, /// 9 D9 = 0x39, #endregion #region 字母区 - 符号 /// 引号 ' Apostrophe = 0xDE, /// 逗号 , Comma = 0xBC, /// 连接符 - Minus = 0xBD, /// 等于号 = Equal = 0xBB, /// 句号 . Period = 0xBE, /// 斜杠 / Slash = 0xBF, /// 反斜杠 \ Backslash = 0xE2, /// 分号 ; Semicolon = 0xBA, /// 左方括号 [ LeftSquareBracket = 0xDB, /// 右方括号 ] RightSquareBracket = 0xDD, /// 波浪号 ` Tilde = 0xC0, #endregion #region 小键盘区 /// Num Lock NumLock = 0x90, /// Num 0 NumPad0 = 0x60, /// Num 1 NumPad1 = 0x61, /// Num 2 NumPad2 = 0x62, /// Num 3 NumPad3 = 0x63, /// Num 4 NumPad4 = 0x64, /// Num 5 NumPad5 = 0x65, /// Num 6 NumPad6 = 0x66, /// Num 7 NumPad7 = 0x67, /// Num 8 NumPad8 = 0x68, /// Num 9 NumPad9 = 0x69, /// Num . Decimal = 0x6E, /// Num / Divide = 0x6F, /// Num * Multiply = 0x6A, /// Num - Subtract = 0x6D, /// Num + Add = 0x6B, /// Num Enter NumEnter = 0x0E, #endregion }