add:快捷键面板

This commit is contained in:
2026-05-01 17:36:53 +08:00
parent 6980abe331
commit 6c7c76958f
10 changed files with 612 additions and 1130 deletions
@@ -99,6 +99,13 @@
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Personalize}" />
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard Header="快捷键" Description="快捷键设置"
IsClickEnabled="True" Click="QuickNavCard_Click" Tag="HotkeyPage">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.KeyboardStandard}" />
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="画板" />
@@ -0,0 +1,187 @@
<ui:Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.HotkeyPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Ink_Canvas.Windows.SettingsViews.Pages"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:controls="clr-namespace:Ink_Canvas.Controls;assembly=InkCanvas.Controls"
xmlns:hk="clr-namespace:Ink_Canvas.Windows"
mc:Ignorable="d"
Title="快捷键">
<ScrollViewer PanningMode="VerticalFirst">
<Grid Margin="59,0,59,0">
<FrameworkElement.Resources>
<sys:Double x:Key="SettingsCardSpacing">4</sys:Double>
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
TargetType="TextBlock">
<Style.Setters>
<Setter Property="Margin" Value="1,30,0,6" />
</Style.Setters>
</Style>
</FrameworkElement.Resources>
<Grid>
<ikw:SimpleStackPanel MaxWidth="1000"
HorizontalAlignment="Stretch"
Spacing="{StaticResource SettingsCardSpacing}">
<ui:InfoBar IsClosable="False"
IsOpen="True"
Severity="Informational"
Title="说明"
Message="在这里可以自定义全局快捷键。全局快捷键在任何情况下都能生效,即使应用程序不在焦点状态。" />
<!-- 鼠标模式 -->
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="鼠标模式" />
<controls:LabeledSettingsCard x:Name="CardEnableHotkeysInMouseMode"
Header="在鼠标模式下启用快捷键"
Description="开启后,即使在鼠标模式下快捷键也会生效"
Icon="{x:Static ui:SegoeFluentIcons.KeyboardStandard}"
SwitchName="ToggleSwitchEnableHotkeysInMouseMode"
Toggled="ToggleSwitchEnableHotkeysInMouseMode_Toggled" />
<!-- 基本操作 -->
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="基本操作" />
<hk:HotkeyItem x:Name="UndoHotkey"
Title="撤销"
Description="撤销上一步操作"
DefaultKey="Z"
DefaultModifiers="Control" />
<hk:HotkeyItem x:Name="RedoHotkey"
Title="重做"
Description="重做上一步操作"
DefaultKey="Y"
DefaultModifiers="Control" />
<hk:HotkeyItem x:Name="ClearHotkey"
Title="清空"
Description="清空当前画板内容"
DefaultKey="E"
DefaultModifiers="Control" />
<hk:HotkeyItem x:Name="PasteHotkey"
Title="粘贴"
Description="粘贴剪贴板内容"
DefaultKey="V"
DefaultModifiers="Control" />
<!-- 工具切换 -->
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="工具切换" />
<hk:HotkeyItem x:Name="SelectToolHotkey"
Title="选择工具"
Description="切换到选择工具"
DefaultKey="S"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="DrawToolHotkey"
Title="绘图工具"
Description="切换到绘图工具"
DefaultKey="D"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="EraserToolHotkey"
Title="橡皮擦工具"
Description="切换到橡皮擦工具"
DefaultKey="E"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="BlackboardToolHotkey"
Title="黑板工具"
Description="切换到黑板工具"
DefaultKey="B"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="QuitDrawToolHotkey"
Title="退出绘图/白板"
Description="退出绘图模式或白板模式"
DefaultKey="Q"
DefaultModifiers="Alt" />
<!-- 画笔设置 -->
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="画笔设置" />
<hk:HotkeyItem x:Name="Pen1Hotkey"
Title="画笔1"
Description="选择画笔1"
DefaultKey="D1"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="Pen2Hotkey"
Title="画笔2"
Description="选择画笔2"
DefaultKey="D2"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="Pen3Hotkey"
Title="画笔3"
Description="选择画笔3"
DefaultKey="D3"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="Pen4Hotkey"
Title="画笔4"
Description="选择画笔4"
DefaultKey="D4"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="Pen5Hotkey"
Title="画笔5"
Description="选择画笔5"
DefaultKey="D5"
DefaultModifiers="Alt" />
<!-- 功能快捷键 -->
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="功能快捷键" />
<hk:HotkeyItem x:Name="DrawLineHotkey"
Title="绘制直线"
Description="绘制直线工具"
DefaultKey="L"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="ScreenshotHotkey"
Title="截图"
Description="保存屏幕截图到桌面"
DefaultKey="C"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="QuickDrawHotkey"
Title="快抽"
Description="打开快抽窗口(与悬浮快抽按钮相同)"
DefaultKey="K"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="HideHotkey"
Title="隐藏"
Description="隐藏应用程序"
DefaultKey="V"
DefaultModifiers="Alt" />
<hk:HotkeyItem x:Name="ExitHotkey"
Title="退出"
Description="退出当前模式或应用程序"
DefaultKey="Escape"
DefaultModifiers="None" />
<!-- 操作按钮 -->
<ikw:SimpleStackPanel Orientation="Horizontal"
HorizontalAlignment="Right"
Spacing="10"
Margin="0,20,0,0">
<Button x:Name="BtnResetToDefault"
Content="重置为默认"
MinWidth="120"
Click="BtnResetToDefault_Click" />
<Button x:Name="BtnSave"
Content="保存设置"
MinWidth="120"
Style="{StaticResource AccentButtonStyle}"
Click="BtnSave_Click" />
</ikw:SimpleStackPanel>
<Rectangle Height="48" />
</ikw:SimpleStackPanel>
</Grid>
</Grid>
</ScrollViewer>
</ui:Page>
@@ -0,0 +1,366 @@
using Ink_Canvas.Helpers;
using Ink_Canvas.Windows;
using Ink_Canvas.Windows.SettingsViews.Helpers;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using MessageBox = iNKORE.UI.WPF.Modern.Controls.MessageBox;
using Page = iNKORE.UI.WPF.Modern.Controls.Page;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class HotkeyPage : Page
{
private bool _isLoaded;
private readonly Dictionary<string, HotkeyItem> _hotkeyItems = new Dictionary<string, HotkeyItem>();
private GlobalHotkeyManager _hotkeyManager;
private MainWindow _mainWindow;
public HotkeyPage()
{
InitializeComponent();
Loaded += HotkeyPage_Loaded;
Unloaded += HotkeyPage_Unloaded;
}
private void HotkeyPage_Loaded(object sender, RoutedEventArgs e)
{
try
{
_mainWindow = Application.Current.MainWindow as MainWindow;
_hotkeyManager = GetHotkeyManager(_mainWindow);
InitializeHotkeyItems();
LoadCurrentHotkeys();
SetupEventHandlers();
LoadMouseModeSetting();
_isLoaded = true;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"快捷键页面初始化时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
private void HotkeyPage_Unloaded(object sender, RoutedEventArgs e)
{
_isLoaded = false;
foreach (var item in _hotkeyItems.Values)
{
item.HotkeyChanged -= OnHotkeyChanged;
}
_hotkeyItems.Clear();
}
private static GlobalHotkeyManager GetHotkeyManager(MainWindow mw)
{
if (mw == null) return null;
var field = typeof(MainWindow).GetField("_globalHotkeyManager",
BindingFlags.NonPublic | BindingFlags.Instance);
return field?.GetValue(mw) as GlobalHotkeyManager;
}
private void InitializeHotkeyItems()
{
_hotkeyItems["Undo"] = UndoHotkey; UndoHotkey.HotkeyName = "Undo";
_hotkeyItems["Redo"] = RedoHotkey; RedoHotkey.HotkeyName = "Redo";
_hotkeyItems["Clear"] = ClearHotkey; ClearHotkey.HotkeyName = "Clear";
_hotkeyItems["Paste"] = PasteHotkey; PasteHotkey.HotkeyName = "Paste";
_hotkeyItems["SelectTool"] = SelectToolHotkey; SelectToolHotkey.HotkeyName = "SelectTool";
_hotkeyItems["DrawTool"] = DrawToolHotkey; DrawToolHotkey.HotkeyName = "DrawTool";
_hotkeyItems["EraserTool"] = EraserToolHotkey; EraserToolHotkey.HotkeyName = "EraserTool";
_hotkeyItems["BlackboardTool"] = BlackboardToolHotkey; BlackboardToolHotkey.HotkeyName = "BlackboardTool";
_hotkeyItems["QuitDrawTool"] = QuitDrawToolHotkey; QuitDrawToolHotkey.HotkeyName = "QuitDrawTool";
_hotkeyItems["Pen1"] = Pen1Hotkey; Pen1Hotkey.HotkeyName = "Pen1";
_hotkeyItems["Pen2"] = Pen2Hotkey; Pen2Hotkey.HotkeyName = "Pen2";
_hotkeyItems["Pen3"] = Pen3Hotkey; Pen3Hotkey.HotkeyName = "Pen3";
_hotkeyItems["Pen4"] = Pen4Hotkey; Pen4Hotkey.HotkeyName = "Pen4";
_hotkeyItems["Pen5"] = Pen5Hotkey; Pen5Hotkey.HotkeyName = "Pen5";
_hotkeyItems["DrawLine"] = DrawLineHotkey; DrawLineHotkey.HotkeyName = "DrawLine";
_hotkeyItems["Screenshot"] = ScreenshotHotkey; ScreenshotHotkey.HotkeyName = "Screenshot";
_hotkeyItems["QuickDraw"] = QuickDrawHotkey; QuickDrawHotkey.HotkeyName = "QuickDraw";
_hotkeyItems["Hide"] = HideHotkey; HideHotkey.HotkeyName = "Hide";
_hotkeyItems["Exit"] = ExitHotkey; ExitHotkey.HotkeyName = "Exit";
}
private void LoadCurrentHotkeys()
{
try
{
if (_hotkeyManager != null)
{
var configHotkeys = _hotkeyManager.GetHotkeysFromConfigFile();
foreach (var hotkey in configHotkeys)
{
if (_hotkeyItems.TryGetValue(hotkey.Name, out var hotkeyItem))
{
hotkeyItem.SetCurrentHotkey(hotkey.Key, hotkey.Modifiers);
}
}
}
foreach (var kvp in _hotkeyItems)
{
var hotkeyItem = kvp.Value;
if (hotkeyItem.GetCurrentHotkey().key == Key.None)
{
SetDefaultHotkeyForItem(hotkeyItem);
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"加载当前快捷键时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
private static void SetDefaultHotkeyForItem(HotkeyItem hotkeyItem)
{
switch (hotkeyItem.HotkeyName)
{
case "Undo": hotkeyItem.SetCurrentHotkey(Key.Z, ModifierKeys.Control); break;
case "Redo": hotkeyItem.SetCurrentHotkey(Key.Y, ModifierKeys.Control); break;
case "Clear": hotkeyItem.SetCurrentHotkey(Key.E, ModifierKeys.Control); break;
case "Paste": hotkeyItem.SetCurrentHotkey(Key.V, ModifierKeys.Control); break;
case "SelectTool": hotkeyItem.SetCurrentHotkey(Key.S, ModifierKeys.Alt); break;
case "DrawTool": hotkeyItem.SetCurrentHotkey(Key.D, ModifierKeys.Alt); break;
case "EraserTool": hotkeyItem.SetCurrentHotkey(Key.E, ModifierKeys.Alt); break;
case "BlackboardTool": hotkeyItem.SetCurrentHotkey(Key.B, ModifierKeys.Alt); break;
case "QuitDrawTool": hotkeyItem.SetCurrentHotkey(Key.Q, ModifierKeys.Alt); break;
case "Pen1": hotkeyItem.SetCurrentHotkey(Key.D1, ModifierKeys.Alt); break;
case "Pen2": hotkeyItem.SetCurrentHotkey(Key.D2, ModifierKeys.Alt); break;
case "Pen3": hotkeyItem.SetCurrentHotkey(Key.D3, ModifierKeys.Alt); break;
case "Pen4": hotkeyItem.SetCurrentHotkey(Key.D4, ModifierKeys.Alt); break;
case "Pen5": hotkeyItem.SetCurrentHotkey(Key.D5, ModifierKeys.Alt); break;
case "DrawLine": hotkeyItem.SetCurrentHotkey(Key.L, ModifierKeys.Alt); break;
case "Screenshot": hotkeyItem.SetCurrentHotkey(Key.C, ModifierKeys.Alt); break;
case "QuickDraw": hotkeyItem.SetCurrentHotkey(Key.K, ModifierKeys.Alt); break;
case "Hide": hotkeyItem.SetCurrentHotkey(Key.V, ModifierKeys.Alt); break;
case "Exit": hotkeyItem.SetCurrentHotkey(Key.Escape, ModifierKeys.None); break;
}
}
private void SetupEventHandlers()
{
foreach (var hotkeyItem in _hotkeyItems.Values)
{
hotkeyItem.HotkeyChanged += OnHotkeyChanged;
}
}
private void LoadMouseModeSetting()
{
CardEnableHotkeysInMouseMode.IsOn = SettingsManager.Settings.Appearance.EnableHotkeysInMouseMode;
}
private void ToggleSwitchEnableHotkeysInMouseMode_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
try
{
bool newState = CardEnableHotkeysInMouseMode.IsOn;
SettingsManager.Settings.Appearance.EnableHotkeysInMouseMode = newState;
SettingsManager.SaveSettingsToFile();
if (_hotkeyManager != null && _mainWindow != null)
{
bool isCurrentlyMouseMode = _mainWindow.inkCanvas.EditingMode == InkCanvasEditingMode.None;
if (isCurrentlyMouseMode && !newState)
{
_hotkeyManager.DisableHotkeyRegistration();
}
else
{
_hotkeyManager.UpdateHotkeyStateForToolMode(isCurrentlyMouseMode);
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"更新鼠标模式快捷键设置时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
private void OnHotkeyChanged(object sender, HotkeyChangedEventArgs e)
{
try
{
if (_hotkeyManager == null)
{
MessageBox.Show("快捷键管理器尚未初始化,无法保存变更。", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
if (IsHotkeyConflict(e.Key, e.Modifiers, e.HotkeyName))
{
MessageBox.Show($"快捷键 {e.Modifiers}+{e.Key} 已被其他功能使用,请选择其他组合。",
"快捷键冲突", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
UpdateHotkeyInManager(e.HotkeyName, e.Key, e.Modifiers);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理快捷键变更时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
private bool IsHotkeyConflict(Key key, ModifierKeys modifiers, string excludeHotkeyName)
{
var registeredHotkeys = _hotkeyManager.GetRegisteredHotkeys();
foreach (var hotkey in registeredHotkeys)
{
if (hotkey.Name != excludeHotkeyName &&
hotkey.Key == key &&
hotkey.Modifiers == modifiers)
{
return true;
}
}
if (excludeHotkeyName != null && _hotkeyItems.TryGetValue(excludeHotkeyName, out var currentItem))
{
var currentHotkey = currentItem.GetCurrentHotkey();
if (currentHotkey.key == Key.None)
{
foreach (var kvp in _hotkeyItems)
{
if (kvp.Key != excludeHotkeyName)
{
var itemHotkey = kvp.Value.GetCurrentHotkey();
if (itemHotkey.key == key && itemHotkey.modifiers == modifiers)
{
return true;
}
}
}
}
}
return false;
}
private void UpdateHotkeyInManager(string hotkeyName, Key key, ModifierKeys modifiers)
{
try
{
_hotkeyManager.UnregisterHotkey(hotkeyName);
var action = GetActionForHotkey(hotkeyName);
if (action == null)
{
LogHelper.WriteLogToFile($"未找到快捷键 {hotkeyName} 对应的动作", LogHelper.LogType.Warning);
return;
}
if (_hotkeyManager.RegisterHotkey(hotkeyName, key, modifiers, action))
{
_hotkeyManager.SaveHotkeysToSettings();
LoadCurrentHotkeys();
LogHelper.WriteLogToFile($"快捷键 {hotkeyName} 已更新为 {modifiers}+{key} 并保存", LogHelper.LogType.Event);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"更新快捷键管理器时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
private Action GetActionForHotkey(string hotkeyName)
{
if (_mainWindow == null) return null;
switch (hotkeyName)
{
case "Undo": return () => _mainWindow.SymbolIconUndo_MouseUp(null, null);
case "Redo": return () => _mainWindow.SymbolIconRedo_MouseUp(null, null);
case "Clear": return () => _mainWindow.SymbolIconDelete_MouseUp(null, null);
case "Paste": return () => _mainWindow.HandleGlobalPaste(null, null);
case "SelectTool": return () => _mainWindow.SymbolIconSelect_MouseUp(null, null);
case "DrawTool": return () => _mainWindow.PenIcon_Click(null, null);
case "EraserTool": return () => _mainWindow.EraserIcon_Click(null, null);
case "BlackboardTool": return () => _mainWindow.ImageBlackboard_MouseUp(null, null);
case "QuitDrawTool": return () => _mainWindow.CursorIcon_Click(null, null);
case "Pen1": return () => SwitchToPenType(0);
case "Pen2": return () => SwitchToPenType(1);
case "Pen3": return () => SwitchToPenType(2);
case "Pen4": return () => SwitchToPenType(3);
case "Pen5": return () => SwitchToPenType(4);
case "DrawLine": return () => _mainWindow.BtnDrawLine_Click(null, null);
case "Screenshot": return () => _mainWindow.SaveScreenShotToDesktop();
case "QuickDraw": return () => _mainWindow.OpenQuickDrawFromHotkey();
case "Hide": return () => _mainWindow.SymbolIconEmoji_MouseUp(null, null);
case "Exit": return () => _mainWindow.KeyExit(null, null);
default: return null;
}
}
private void SwitchToPenType(int penTypeIndex)
{
try
{
if (_mainWindow == null) return;
var penTypeField = _mainWindow.GetType().GetField("penType",
BindingFlags.NonPublic | BindingFlags.Instance);
if (penTypeField != null)
{
penTypeField.SetValue(_mainWindow, penTypeIndex);
var checkPenTypeMethod = _mainWindow.GetType().GetMethod("CheckPenTypeUIState",
BindingFlags.NonPublic | BindingFlags.Instance);
checkPenTypeMethod?.Invoke(_mainWindow, null);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"切换到笔类型{penTypeIndex}时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
private void BtnResetToDefault_Click(object sender, RoutedEventArgs e)
{
try
{
if (_hotkeyManager == null) return;
var result = MessageBox.Show("确定要重置所有快捷键为默认设置吗?", "确认重置",
MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result != MessageBoxResult.Yes) return;
_hotkeyManager.UnregisterAllHotkeys();
_hotkeyManager.RegisterDefaultHotkeys();
_hotkeyManager.SaveHotkeysToSettings();
LoadCurrentHotkeys();
MessageBox.Show("快捷键已重置为默认设置。", "重置完成",
MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"重置快捷键时出错: {ex.Message}", LogHelper.LogType.Error);
MessageBox.Show($"重置快捷键时出错: {ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void BtnSave_Click(object sender, RoutedEventArgs e)
{
try
{
if (_hotkeyManager == null) return;
_hotkeyManager.SaveHotkeysToSettings();
MessageBox.Show("快捷键设置已保存。", "保存成功",
MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"保存快捷键设置时出错: {ex.Message}", LogHelper.LogType.Error);
MessageBox.Show($"保存快捷键设置时出错: {ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}