improve:issue #112
This commit is contained in:
@@ -0,0 +1,301 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Input;
|
||||
using NHotkey.Wpf;
|
||||
|
||||
namespace Ink_Canvas.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局快捷键管理器 - 使用NHotkey库实现全局快捷键功能
|
||||
/// </summary>
|
||||
public class GlobalHotkeyManager : IDisposable
|
||||
{
|
||||
#region Private Fields
|
||||
private readonly Dictionary<string, HotkeyInfo> _registeredHotkeys;
|
||||
private readonly MainWindow _mainWindow;
|
||||
private bool _isDisposed = false;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public GlobalHotkeyManager(MainWindow mainWindow)
|
||||
{
|
||||
_mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow));
|
||||
_registeredHotkeys = new Dictionary<string, HotkeyInfo>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// 注册全局快捷键
|
||||
/// </summary>
|
||||
/// <param name="hotkeyName">快捷键名称</param>
|
||||
/// <param name="key">按键</param>
|
||||
/// <param name="modifiers">修饰键</param>
|
||||
/// <param name="action">执行动作</param>
|
||||
/// <returns>是否注册成功</returns>
|
||||
public bool RegisterHotkey(string hotkeyName, Key key, ModifierKeys modifiers, Action action)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_isDisposed)
|
||||
return false;
|
||||
|
||||
// 如果快捷键已存在,先注销
|
||||
if (_registeredHotkeys.ContainsKey(hotkeyName))
|
||||
{
|
||||
UnregisterHotkey(hotkeyName);
|
||||
}
|
||||
|
||||
// 创建快捷键信息
|
||||
var hotkeyInfo = new HotkeyInfo
|
||||
{
|
||||
Name = hotkeyName,
|
||||
Key = key,
|
||||
Modifiers = modifiers,
|
||||
Action = action
|
||||
};
|
||||
|
||||
// 注册快捷键
|
||||
HotkeyManager.Current.AddOrReplace(hotkeyName, key, modifiers, (sender, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// 确保在主线程中执行
|
||||
_mainWindow.Dispatcher.Invoke(() =>
|
||||
{
|
||||
action?.Invoke();
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"执行快捷键 {hotkeyName} 时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
});
|
||||
|
||||
_registeredHotkeys[hotkeyName] = hotkeyInfo;
|
||||
LogHelper.WriteLogToFile($"成功注册全局快捷键: {hotkeyName} ({modifiers}+{key})", LogHelper.LogType.Event);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"注册全局快捷键 {hotkeyName} 失败: {ex.Message}", LogHelper.LogType.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注销指定快捷键
|
||||
/// </summary>
|
||||
/// <param name="hotkeyName">快捷键名称</param>
|
||||
/// <returns>是否注销成功</returns>
|
||||
public bool UnregisterHotkey(string hotkeyName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_isDisposed || !_registeredHotkeys.ContainsKey(hotkeyName))
|
||||
return false;
|
||||
|
||||
HotkeyManager.Current.Remove(hotkeyName);
|
||||
_registeredHotkeys.Remove(hotkeyName);
|
||||
LogHelper.WriteLogToFile($"成功注销全局快捷键: {hotkeyName}", LogHelper.LogType.Event);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"注销全局快捷键 {hotkeyName} 失败: {ex.Message}", LogHelper.LogType.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注销所有快捷键
|
||||
/// </summary>
|
||||
public void UnregisterAllHotkeys()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
foreach (var hotkeyName in _registeredHotkeys.Keys)
|
||||
{
|
||||
try
|
||||
{
|
||||
HotkeyManager.Current.Remove(hotkeyName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"注销快捷键 {hotkeyName} 时出错: {ex.Message}", LogHelper.LogType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
_registeredHotkeys.Clear();
|
||||
LogHelper.WriteLogToFile("已注销所有全局快捷键", LogHelper.LogType.Event);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"注销所有快捷键时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查快捷键是否已注册
|
||||
/// </summary>
|
||||
/// <param name="hotkeyName">快捷键名称</param>
|
||||
/// <returns>是否已注册</returns>
|
||||
public bool IsHotkeyRegistered(string hotkeyName)
|
||||
{
|
||||
return _registeredHotkeys.ContainsKey(hotkeyName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取已注册的快捷键列表
|
||||
/// </summary>
|
||||
/// <returns>快捷键信息列表</returns>
|
||||
public List<HotkeyInfo> GetRegisteredHotkeys()
|
||||
{
|
||||
return new List<HotkeyInfo>(_registeredHotkeys.Values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册默认快捷键集合
|
||||
/// </summary>
|
||||
public void RegisterDefaultHotkeys()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 基本操作快捷键
|
||||
RegisterHotkey("Undo", Key.Z, ModifierKeys.Control, () => _mainWindow.SymbolIconUndo_MouseUp(null, null));
|
||||
RegisterHotkey("Redo", Key.Y, ModifierKeys.Control, () => _mainWindow.SymbolIconRedo_MouseUp(null, null));
|
||||
RegisterHotkey("Clear", Key.E, ModifierKeys.Control, () => _mainWindow.SymbolIconDelete_MouseUp(null, null));
|
||||
RegisterHotkey("Paste", Key.V, ModifierKeys.Control, () => _mainWindow.HandleGlobalPaste(null, null));
|
||||
|
||||
// 工具切换快捷键
|
||||
RegisterHotkey("SelectTool", Key.S, ModifierKeys.Alt, () => _mainWindow.SymbolIconSelect_MouseUp(null, null));
|
||||
RegisterHotkey("DrawTool", Key.D, ModifierKeys.Alt, () => _mainWindow.PenIcon_Click(null, null));
|
||||
RegisterHotkey("EraserTool", Key.E, ModifierKeys.Alt, () => _mainWindow.EraserIcon_Click(null, null));
|
||||
RegisterHotkey("BlackboardTool", Key.B, ModifierKeys.Alt, () => _mainWindow.ImageBlackboard_MouseUp(null, null));
|
||||
RegisterHotkey("QuitDrawTool", Key.Q, ModifierKeys.Alt, () => _mainWindow.CursorIcon_Click(null, null));
|
||||
|
||||
// 画笔快捷键 - 使用反射访问penType字段
|
||||
RegisterHotkey("Pen1", Key.D1, ModifierKeys.Alt, () => SwitchToPenType(0));
|
||||
RegisterHotkey("Pen2", Key.D2, ModifierKeys.Alt, () => SwitchToPenType(1));
|
||||
RegisterHotkey("Pen3", Key.D3, ModifierKeys.Alt, () => SwitchToPenType(2));
|
||||
RegisterHotkey("Pen4", Key.D4, ModifierKeys.Alt, () => SwitchToPenType(3));
|
||||
RegisterHotkey("Pen5", Key.D5, ModifierKeys.Alt, () => SwitchToPenType(4));
|
||||
|
||||
// 功能快捷键
|
||||
RegisterHotkey("DrawLine", Key.L, ModifierKeys.Alt, () => _mainWindow.BtnDrawLine_Click(null, null));
|
||||
RegisterHotkey("Screenshot", Key.C, ModifierKeys.Alt, () => _mainWindow.SaveScreenShotToDesktop());
|
||||
RegisterHotkey("Hide", Key.V, ModifierKeys.Alt, () => _mainWindow.SymbolIconEmoji_MouseUp(null, null));
|
||||
|
||||
// 退出快捷键
|
||||
RegisterHotkey("Exit", Key.Escape, ModifierKeys.None, () => _mainWindow.KeyExit(null, null));
|
||||
|
||||
LogHelper.WriteLogToFile("已注册默认全局快捷键集合", LogHelper.LogType.Event);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"注册默认快捷键时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从设置加载快捷键配置
|
||||
/// </summary>
|
||||
public void LoadHotkeysFromSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 这里可以从配置文件或设置中加载自定义快捷键
|
||||
// 暂时使用默认快捷键
|
||||
RegisterDefaultHotkeys();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"从设置加载快捷键时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存快捷键配置到设置
|
||||
/// </summary>
|
||||
public void SaveHotkeysToSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 这里可以将快捷键配置保存到配置文件或设置中
|
||||
LogHelper.WriteLogToFile("快捷键配置已保存", LogHelper.LogType.Event);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"保存快捷键配置时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Helper Methods
|
||||
/// <summary>
|
||||
/// 切换到指定笔类型
|
||||
/// </summary>
|
||||
/// <param name="penTypeIndex">笔类型索引</param>
|
||||
private void SwitchToPenType(int penTypeIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 通过反射访问主窗口的penType字段
|
||||
var penTypeField = _mainWindow.GetType().GetField("penType",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
|
||||
if (penTypeField != null)
|
||||
{
|
||||
penTypeField.SetValue(_mainWindow, penTypeIndex);
|
||||
|
||||
// 调用CheckPenTypeUIState方法更新UI状态
|
||||
var checkPenTypeMethod = _mainWindow.GetType().GetMethod("CheckPenTypeUIState",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
|
||||
if (checkPenTypeMethod != null)
|
||||
{
|
||||
checkPenTypeMethod.Invoke(_mainWindow, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"切换到笔类型{penTypeIndex}时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable Implementation
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
UnregisterAllHotkeys();
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Nested Classes
|
||||
/// <summary>
|
||||
/// 快捷键信息类
|
||||
/// </summary>
|
||||
public class HotkeyInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Key Key { get; set; }
|
||||
public ModifierKeys Modifiers { get; set; }
|
||||
public Action Action { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var modifiersText = Modifiers == ModifierKeys.None ? "" : $"{Modifiers}+";
|
||||
return $"{modifiersText}{Key}";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Threading;
|
||||
using System.Windows.Ink;
|
||||
|
||||
namespace Ink_Canvas.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// 墨迹渐隐管理器 - 管理墨迹的渐隐动画和状态
|
||||
/// </summary>
|
||||
public class InkFadeManager
|
||||
{
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// 是否启用墨迹渐隐功能
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 墨迹渐隐时间(毫秒)
|
||||
/// </summary>
|
||||
public int FadeTime { get; set; } = 3000;
|
||||
|
||||
/// <summary>
|
||||
/// 渐隐动画持续时间(毫秒)
|
||||
/// </summary>
|
||||
public int AnimationDuration { get; set; } = 1000;
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
private readonly MainWindow _mainWindow;
|
||||
private readonly Dispatcher _dispatcher;
|
||||
private readonly Dictionary<Stroke, DispatcherTimer> _fadeTimers;
|
||||
private readonly Dictionary<Stroke, UIElement> _strokeVisuals;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public InkFadeManager(MainWindow mainWindow)
|
||||
{
|
||||
_mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow));
|
||||
_dispatcher = _mainWindow.Dispatcher;
|
||||
_fadeTimers = new Dictionary<Stroke, DispatcherTimer>();
|
||||
_strokeVisuals = new Dictionary<Stroke, UIElement>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// 添加需要渐隐的墨迹
|
||||
/// </summary>
|
||||
/// <param name="stroke">墨迹对象</param>
|
||||
/// <param name="visual">墨迹的视觉元素</param>
|
||||
public void AddFadingStroke(Stroke stroke, UIElement visual)
|
||||
{
|
||||
if (!IsEnabled || stroke == null || visual == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
// 记录墨迹和视觉元素的对应关系
|
||||
_strokeVisuals[stroke] = visual;
|
||||
|
||||
// 创建定时器,在指定时间后开始渐隐动画
|
||||
var timer = new DispatcherTimer
|
||||
{
|
||||
Interval = TimeSpan.FromMilliseconds(FadeTime)
|
||||
};
|
||||
|
||||
timer.Tick += (sender, e) =>
|
||||
{
|
||||
StartFadeAnimation(stroke);
|
||||
timer.Stop();
|
||||
_fadeTimers.Remove(stroke);
|
||||
};
|
||||
|
||||
_fadeTimers[stroke] = timer;
|
||||
timer.Start();
|
||||
|
||||
// 将视觉元素添加到画布上
|
||||
_dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_mainWindow.inkCanvas != null)
|
||||
{
|
||||
_mainWindow.inkCanvas.Children.Add(visual);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"添加墨迹视觉元素到画布失败: {ex}", LogHelper.LogType.Error);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"添加渐隐墨迹失败: {ex}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除墨迹
|
||||
/// </summary>
|
||||
/// <param name="stroke">要移除的墨迹</param>
|
||||
public void RemoveStroke(Stroke stroke)
|
||||
{
|
||||
if (stroke == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (_fadeTimers.TryGetValue(stroke, out var timer))
|
||||
{
|
||||
timer.Stop();
|
||||
_fadeTimers.Remove(stroke);
|
||||
}
|
||||
|
||||
if (_strokeVisuals.TryGetValue(stroke, out var visual))
|
||||
{
|
||||
_dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_mainWindow.inkCanvas != null && _mainWindow.inkCanvas.Children.Contains(visual))
|
||||
{
|
||||
_mainWindow.inkCanvas.Children.Remove(visual);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"从画布移除墨迹视觉元素失败: {ex}", LogHelper.LogType.Error);
|
||||
}
|
||||
});
|
||||
|
||||
_strokeVisuals.Remove(stroke);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"移除渐隐墨迹失败: {ex}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有渐隐墨迹
|
||||
/// </summary>
|
||||
public void ClearAllFadingStrokes()
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var timer in _fadeTimers.Values)
|
||||
{
|
||||
timer.Stop();
|
||||
}
|
||||
|
||||
_fadeTimers.Clear();
|
||||
|
||||
_dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_mainWindow.inkCanvas != null)
|
||||
{
|
||||
foreach (var visual in _strokeVisuals.Values)
|
||||
{
|
||||
if (_mainWindow.inkCanvas.Children.Contains(visual))
|
||||
{
|
||||
_mainWindow.inkCanvas.Children.Remove(visual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"清除所有墨迹视觉元素失败: {ex}", LogHelper.LogType.Error);
|
||||
}
|
||||
});
|
||||
|
||||
_strokeVisuals.Clear();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"清除所有渐隐墨迹失败: {ex}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新渐隐时间设置
|
||||
/// </summary>
|
||||
/// <param name="fadeTime">新的渐隐时间(毫秒)</param>
|
||||
public void UpdateFadeTime(int fadeTime)
|
||||
{
|
||||
FadeTime = fadeTime;
|
||||
|
||||
foreach (var kvp in _fadeTimers)
|
||||
{
|
||||
var stroke = kvp.Key;
|
||||
var timer = kvp.Value;
|
||||
|
||||
timer.Stop();
|
||||
timer.Interval = TimeSpan.FromMilliseconds(FadeTime);
|
||||
timer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新动画持续时间设置
|
||||
/// </summary>
|
||||
/// <param name="animationDuration">新的动画持续时间(毫秒)</param>
|
||||
public void UpdateAnimationDuration(int animationDuration)
|
||||
{
|
||||
AnimationDuration = animationDuration;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// 开始渐隐动画
|
||||
/// </summary>
|
||||
/// <param name="stroke">要渐隐的墨迹</param>
|
||||
private void StartFadeAnimation(Stroke stroke)
|
||||
{
|
||||
if (!_strokeVisuals.TryGetValue(stroke, out var visual)) return;
|
||||
|
||||
try
|
||||
{
|
||||
_dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var fadeAnimation = new DoubleAnimation
|
||||
{
|
||||
From = 1.0,
|
||||
To = 0.0,
|
||||
Duration = TimeSpan.FromMilliseconds(AnimationDuration),
|
||||
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut }
|
||||
};
|
||||
|
||||
fadeAnimation.Completed += (sender, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_mainWindow.inkCanvas != null && _mainWindow.inkCanvas.Children.Contains(visual))
|
||||
{
|
||||
_mainWindow.inkCanvas.Children.Remove(visual);
|
||||
}
|
||||
|
||||
RemoveStroke(stroke);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"渐隐动画完成后清理墨迹失败: {ex}", LogHelper.LogType.Error);
|
||||
}
|
||||
};
|
||||
|
||||
visual.BeginAnimation(UIElement.OpacityProperty, fadeAnimation);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"开始渐隐动画失败: {ex}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using Ink_Canvas.Helpers;
|
||||
|
||||
namespace Ink_Canvas.Helpers
|
||||
{
|
||||
|
||||
@@ -41,6 +41,9 @@ namespace Ink_Canvas
|
||||
private int currentPageIndex;
|
||||
private System.Windows.Controls.Canvas currentCanvas;
|
||||
private AutoUpdateHelper.UpdateLineGroup AvailableLatestLineGroup;
|
||||
|
||||
// 全局快捷键管理器
|
||||
private GlobalHotkeyManager _globalHotkeyManager;
|
||||
|
||||
|
||||
|
||||
@@ -495,6 +498,9 @@ namespace Ink_Canvas
|
||||
|
||||
// 初始化剪贴板监控
|
||||
InitializeClipboardMonitoring();
|
||||
|
||||
// 初始化全局快捷键管理器
|
||||
InitializeGlobalHotkeyManager();
|
||||
}
|
||||
|
||||
private void SystemEventsOnDisplaySettingsChanged(object sender, EventArgs e)
|
||||
@@ -623,6 +629,13 @@ namespace Ink_Canvas
|
||||
// 清理剪贴板监控
|
||||
CleanupClipboardMonitoring();
|
||||
ClipboardNotification.Stop();
|
||||
|
||||
// 清理全局快捷键管理器
|
||||
if (_globalHotkeyManager != null)
|
||||
{
|
||||
_globalHotkeyManager.Dispose();
|
||||
_globalHotkeyManager = null;
|
||||
}
|
||||
|
||||
// 停止置顶维护定时器
|
||||
StopTopmostMaintenance();
|
||||
@@ -1067,10 +1080,7 @@ namespace Ink_Canvas
|
||||
// 新增:快捷键设置
|
||||
private void NavShortcuts_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到快捷键设置页面
|
||||
ShowSettingsSection("shortcuts");
|
||||
// 如果设置部分尚未快捷键
|
||||
MessageBox.Show("设置功能正在开发中", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
OpenHotkeySettingsWindow();
|
||||
}
|
||||
|
||||
private void BtnCloseSettings_Click(object sender, RoutedEventArgs e)
|
||||
@@ -1955,5 +1965,46 @@ namespace Ink_Canvas
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 全局快捷键管理
|
||||
/// <summary>
|
||||
/// 初始化全局快捷键管理器
|
||||
/// </summary>
|
||||
private void InitializeGlobalHotkeyManager()
|
||||
{
|
||||
try
|
||||
{
|
||||
_globalHotkeyManager = new GlobalHotkeyManager(this);
|
||||
_globalHotkeyManager.LoadHotkeysFromSettings();
|
||||
LogHelper.WriteLogToFile("全局快捷键管理器已初始化", LogHelper.LogType.Event);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"初始化全局快捷键管理器时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开快捷键设置窗口
|
||||
/// </summary>
|
||||
private void OpenHotkeySettingsWindow()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_globalHotkeyManager == null)
|
||||
{
|
||||
MessageBox.Show("快捷键管理器尚未初始化,请稍后重试。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
var hotkeySettingsWindow = new HotkeySettingsWindow(this, _globalHotkeyManager);
|
||||
hotkeySettingsWindow.ShowDialog();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"打开快捷键设置窗口时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
MessageBox.Show($"打开快捷键设置窗口时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ namespace Ink_Canvas
|
||||
}
|
||||
|
||||
// 处理全局粘贴快捷键
|
||||
private async void HandleGlobalPaste(object sender, ExecutedRoutedEventArgs e)
|
||||
internal async void HandleGlobalPaste(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace Ink_Canvas
|
||||
GridForFloatingBarDraging.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void SymbolIconEmoji_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
internal void SymbolIconEmoji_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
isDragDropInEffect = false;
|
||||
|
||||
@@ -495,7 +495,8 @@ namespace Ink_Canvas
|
||||
#endregion
|
||||
|
||||
#region 撤銷重做按鈕
|
||||
private void SymbolIconUndo_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
|
||||
internal void SymbolIconUndo_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
//if (lastBorderMouseDownObject != sender) return;
|
||||
|
||||
@@ -508,7 +509,7 @@ namespace Ink_Canvas
|
||||
HideSubPanels();
|
||||
}
|
||||
|
||||
private void SymbolIconRedo_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
internal void SymbolIconRedo_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
//if (lastBorderMouseDownObject != sender) return;
|
||||
|
||||
@@ -528,7 +529,7 @@ namespace Ink_Canvas
|
||||
//private bool Not_Enter_Blackboard_fir_Mouse_Click = true;
|
||||
private bool isDisplayingOrHidingBlackboard;
|
||||
|
||||
private void ImageBlackboard_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
internal void ImageBlackboard_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
|
||||
if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
|
||||
@@ -728,7 +729,7 @@ namespace Ink_Canvas
|
||||
|
||||
#region 清空畫布按鈕
|
||||
|
||||
private void SymbolIconDelete_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
internal void SymbolIconDelete_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
|
||||
if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
|
||||
@@ -778,7 +779,7 @@ namespace Ink_Canvas
|
||||
/// </summary>
|
||||
/// <param name="sender">sender</param>
|
||||
/// <param name="e">MouseButtonEventArgs</param>
|
||||
private void SymbolIconSelect_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
internal void SymbolIconSelect_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
|
||||
if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
|
||||
@@ -1542,7 +1543,7 @@ namespace Ink_Canvas
|
||||
});
|
||||
}
|
||||
|
||||
private async void CursorIcon_Click(object sender, RoutedEventArgs e)
|
||||
internal async void CursorIcon_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
|
||||
((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
|
||||
@@ -1648,7 +1649,7 @@ namespace Ink_Canvas
|
||||
}
|
||||
}
|
||||
|
||||
private void PenIcon_Click(object sender, RoutedEventArgs e)
|
||||
internal void PenIcon_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
|
||||
@@ -1866,7 +1867,7 @@ namespace Ink_Canvas
|
||||
CheckColorTheme();
|
||||
}
|
||||
|
||||
private void EraserIcon_Click(object sender, RoutedEventArgs e)
|
||||
internal void EraserIcon_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
EnterMultiTouchModeIfNeeded();
|
||||
bool isAlreadyEraser = inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint;
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Ink_Canvas
|
||||
}
|
||||
|
||||
|
||||
private void KeyExit(object sender, ExecutedRoutedEventArgs e)
|
||||
internal void KeyExit(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) BtnPPTSlideShowEnd_Click(BtnPPTSlideShowEnd, null);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Ink_Canvas
|
||||
SaveInkCanvasStrokes(false);
|
||||
}
|
||||
|
||||
private void SaveScreenShotToDesktop()
|
||||
internal void SaveScreenShotToDesktop()
|
||||
{
|
||||
var desktopPath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
|
||||
|
||||
@@ -172,8 +172,8 @@ namespace Ink_Canvas
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
private async void BtnDrawLine_Click(object sender, MouseButtonEventArgs e)
|
||||
|
||||
internal async void BtnDrawLine_Click(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
await CheckIsDrawingShapesInMultiTouchMode();
|
||||
EnterShapeDrawingMode(1);
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<UserControl x:Class="Ink_Canvas.Windows.HotkeyItem"
|
||||
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:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="60" d:DesignWidth="600">
|
||||
|
||||
<Border Background="White"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5"
|
||||
Margin="0,2">
|
||||
<Grid Margin="15,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 左侧信息 -->
|
||||
<ui:SimpleStackPanel Grid.Column="0" VerticalAlignment="Center">
|
||||
<TextBlock x:Name="TitleTextBlock"
|
||||
Text="快捷键标题"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#333333"/>
|
||||
<TextBlock x:Name="DescriptionTextBlock"
|
||||
Text="快捷键描述"
|
||||
FontSize="12"
|
||||
Foreground="#666666"
|
||||
Margin="0,2,0,0"/>
|
||||
</ui:SimpleStackPanel>
|
||||
|
||||
<!-- 当前快捷键显示 -->
|
||||
<Border Grid.Column="1"
|
||||
Background="#F5F5F5"
|
||||
BorderBrush="#D0D0D0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="3"
|
||||
Margin="10,0,0,0"
|
||||
Padding="8,4">
|
||||
<TextBlock x:Name="CurrentHotkeyTextBlock"
|
||||
Text="未设置"
|
||||
FontSize="12"
|
||||
Foreground="#666666"
|
||||
MinWidth="80"
|
||||
TextAlignment="Center"/>
|
||||
</Border>
|
||||
|
||||
<!-- 设置按钮 -->
|
||||
<Button x:Name="BtnSetHotkey"
|
||||
Grid.Column="2"
|
||||
Content="设置"
|
||||
Width="60"
|
||||
Height="28"
|
||||
Background="#0066BF"
|
||||
Foreground="White"
|
||||
FontSize="12"
|
||||
Margin="10,0,0,0"
|
||||
Click="BtnSetHotkey_Click"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Ink_Canvas.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// 快捷键项控件
|
||||
/// </summary>
|
||||
public partial class HotkeyItem : UserControl
|
||||
{
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// 快捷键变更事件
|
||||
/// </summary>
|
||||
public event EventHandler<HotkeyChangedEventArgs> HotkeyChanged;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public string Title
|
||||
{
|
||||
get => TitleTextBlock.Text;
|
||||
set => TitleTextBlock.Text = value;
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get => DescriptionTextBlock.Text;
|
||||
set => DescriptionTextBlock.Text = value;
|
||||
}
|
||||
|
||||
public string DefaultKey { get; set; }
|
||||
public string DefaultModifiers { get; set; }
|
||||
|
||||
private Key _currentKey = Key.None;
|
||||
private ModifierKeys _currentModifiers = ModifierKeys.None;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public HotkeyItem()
|
||||
{
|
||||
InitializeComponent();
|
||||
UpdateHotkeyDisplay();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// 设置当前快捷键
|
||||
/// </summary>
|
||||
/// <param name="key">按键</param>
|
||||
/// <param name="modifiers">修饰键</param>
|
||||
public void SetCurrentHotkey(Key key, ModifierKeys modifiers)
|
||||
{
|
||||
_currentKey = key;
|
||||
_currentModifiers = modifiers;
|
||||
UpdateHotkeyDisplay();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前快捷键
|
||||
/// </summary>
|
||||
/// <returns>快捷键信息</returns>
|
||||
public (Key key, ModifierKeys modifiers) GetCurrentHotkey()
|
||||
{
|
||||
return (_currentKey, _currentModifiers);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void UpdateHotkeyDisplay()
|
||||
{
|
||||
if (_currentKey == Key.None)
|
||||
{
|
||||
CurrentHotkeyTextBlock.Text = "未设置";
|
||||
CurrentHotkeyTextBlock.Foreground = System.Windows.Media.Brushes.Gray;
|
||||
}
|
||||
else
|
||||
{
|
||||
var modifiersText = _currentModifiers == ModifierKeys.None ? "" : $"{_currentModifiers}+";
|
||||
CurrentHotkeyTextBlock.Text = $"{modifiersText}{_currentKey}";
|
||||
CurrentHotkeyTextBlock.Foreground = System.Windows.Media.Brushes.Black;
|
||||
}
|
||||
}
|
||||
|
||||
private void StartHotkeyCapture()
|
||||
{
|
||||
BtnSetHotkey.Content = "请按键...";
|
||||
BtnSetHotkey.Background = System.Windows.Media.Brushes.Orange;
|
||||
|
||||
// 设置焦点以捕获键盘事件
|
||||
Focus();
|
||||
|
||||
// 添加键盘事件处理器
|
||||
KeyDown += HotkeyItem_KeyDown;
|
||||
KeyUp += HotkeyItem_KeyUp;
|
||||
}
|
||||
|
||||
private void StopHotkeyCapture()
|
||||
{
|
||||
BtnSetHotkey.Content = "设置";
|
||||
BtnSetHotkey.Background = System.Windows.Media.Brushes.DodgerBlue;
|
||||
|
||||
// 移除键盘事件处理器
|
||||
KeyDown -= HotkeyItem_KeyDown;
|
||||
KeyUp -= HotkeyItem_KeyUp;
|
||||
}
|
||||
|
||||
private void HotkeyItem_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
// 忽略某些特殊键
|
||||
if (e.Key == Key.LeftShift || e.Key == Key.RightShift ||
|
||||
e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl ||
|
||||
e.Key == Key.LeftAlt || e.Key == Key.RightAlt ||
|
||||
e.Key == Key.LWin || e.Key == Key.RWin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取修饰键
|
||||
var modifiers = ModifierKeys.None;
|
||||
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
||||
modifiers |= ModifierKeys.Control;
|
||||
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
|
||||
modifiers |= ModifierKeys.Shift;
|
||||
if (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt))
|
||||
modifiers |= ModifierKeys.Alt;
|
||||
if (Keyboard.IsKeyDown(Key.LWin) || Keyboard.IsKeyDown(Key.RWin))
|
||||
modifiers |= ModifierKeys.Windows;
|
||||
|
||||
// 设置新的快捷键
|
||||
var oldKey = _currentKey;
|
||||
var oldModifiers = _currentModifiers;
|
||||
|
||||
_currentKey = e.Key;
|
||||
_currentModifiers = modifiers;
|
||||
|
||||
UpdateHotkeyDisplay();
|
||||
StopHotkeyCapture();
|
||||
|
||||
// 触发快捷键变更事件
|
||||
HotkeyChanged?.Invoke(this, new HotkeyChangedEventArgs
|
||||
{
|
||||
HotkeyName = Title,
|
||||
Key = _currentKey,
|
||||
Modifiers = _currentModifiers
|
||||
});
|
||||
}
|
||||
|
||||
private void HotkeyItem_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
private void BtnSetHotkey_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
StartHotkeyCapture();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
<Window x:Class="Ink_Canvas.Windows.HotkeySettingsWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Ink_Canvas.Windows"
|
||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
ui:ThemeManager.RequestedTheme="Light"
|
||||
Topmost="True"
|
||||
Background="Transparent"
|
||||
AllowsTransparency="True"
|
||||
mc:Ignorable="d"
|
||||
WindowStyle="None"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Title="快捷键设置"
|
||||
Height="600"
|
||||
Width="800">
|
||||
|
||||
<Border Background="#F0F3F9" CornerRadius="10" BorderThickness="1" BorderBrush="#0066BF" Margin="10">
|
||||
<Grid>
|
||||
<!-- 标题栏 -->
|
||||
<Border Height="50" Background="#0066BF" CornerRadius="10,10,0,0" VerticalAlignment="Top">
|
||||
<Grid>
|
||||
<TextBlock Text="快捷键设置"
|
||||
Foreground="White"
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"/>
|
||||
<Button x:Name="BtnClose"
|
||||
Content="✕"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Background="Transparent"
|
||||
Foreground="White"
|
||||
FontSize="14"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,30,0"
|
||||
Click="BtnClose_Click"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<ScrollViewer Margin="0,50,0,0" VerticalScrollBarVisibility="Auto">
|
||||
<ui:SimpleStackPanel Margin="20">
|
||||
<!-- 说明文字 -->
|
||||
<TextBlock Text="在这里可以自定义全局快捷键设置。全局快捷键在任何情况下都能生效,即使应用程序不在焦点状态。"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,20"
|
||||
Foreground="#666666"/>
|
||||
|
||||
<!-- 快捷键列表 -->
|
||||
<ui:SimpleStackPanel x:Name="HotkeyList" Margin="0,0,0,20">
|
||||
<!-- 基本操作 -->
|
||||
<GroupBox Header="基本操作" Margin="0,0,0,15">
|
||||
<ui:SimpleStackPanel>
|
||||
<local:HotkeyItem x:Name="UndoHotkey"
|
||||
Title="撤销"
|
||||
Description="撤销上一步操作"
|
||||
DefaultKey="Z"
|
||||
DefaultModifiers="Control"/>
|
||||
<local:HotkeyItem x:Name="RedoHotkey"
|
||||
Title="重做"
|
||||
Description="重做上一步操作"
|
||||
DefaultKey="Y"
|
||||
DefaultModifiers="Control"/>
|
||||
<local:HotkeyItem x:Name="ClearHotkey"
|
||||
Title="清空"
|
||||
Description="清空当前画板内容"
|
||||
DefaultKey="E"
|
||||
DefaultModifiers="Control"/>
|
||||
<local:HotkeyItem x:Name="PasteHotkey"
|
||||
Title="粘贴"
|
||||
Description="粘贴剪贴板内容"
|
||||
DefaultKey="V"
|
||||
DefaultModifiers="Control"/>
|
||||
</ui:SimpleStackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 工具切换 -->
|
||||
<GroupBox Header="工具切换" Margin="0,0,0,15">
|
||||
<ui:SimpleStackPanel>
|
||||
<local:HotkeyItem x:Name="SelectToolHotkey"
|
||||
Title="选择工具"
|
||||
Description="切换到选择工具"
|
||||
DefaultKey="S"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="DrawToolHotkey"
|
||||
Title="绘图工具"
|
||||
Description="切换到绘图工具"
|
||||
DefaultKey="D"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="EraserToolHotkey"
|
||||
Title="橡皮擦工具"
|
||||
Description="切换到橡皮擦工具"
|
||||
DefaultKey="E"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="BlackboardToolHotkey"
|
||||
Title="黑板工具"
|
||||
Description="切换到黑板工具"
|
||||
DefaultKey="B"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="QuitDrawToolHotkey"
|
||||
Title="退出绘图"
|
||||
Description="退出绘图模式"
|
||||
DefaultKey="Q"
|
||||
DefaultModifiers="Alt"/>
|
||||
</ui:SimpleStackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 画笔设置 -->
|
||||
<GroupBox Header="画笔设置" Margin="0,0,0,15">
|
||||
<ui:SimpleStackPanel>
|
||||
<local:HotkeyItem x:Name="Pen1Hotkey"
|
||||
Title="画笔1"
|
||||
Description="选择画笔1"
|
||||
DefaultKey="D1"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="Pen2Hotkey"
|
||||
Title="画笔2"
|
||||
Description="选择画笔2"
|
||||
DefaultKey="D2"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="Pen3Hotkey"
|
||||
Title="画笔3"
|
||||
Description="选择画笔3"
|
||||
DefaultKey="D3"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="Pen4Hotkey"
|
||||
Title="画笔4"
|
||||
Description="选择画笔4"
|
||||
DefaultKey="D4"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="Pen5Hotkey"
|
||||
Title="画笔5"
|
||||
Description="选择画笔5"
|
||||
DefaultKey="D5"
|
||||
DefaultModifiers="Alt"/>
|
||||
</ui:SimpleStackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 功能快捷键 -->
|
||||
<GroupBox Header="功能快捷键" Margin="0,0,0,15">
|
||||
<ui:SimpleStackPanel>
|
||||
<local:HotkeyItem x:Name="DrawLineHotkey"
|
||||
Title="绘制直线"
|
||||
Description="绘制直线工具"
|
||||
DefaultKey="L"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="ScreenshotHotkey"
|
||||
Title="截图"
|
||||
Description="保存屏幕截图到桌面"
|
||||
DefaultKey="C"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="HideHotkey"
|
||||
Title="隐藏"
|
||||
Description="隐藏应用程序"
|
||||
DefaultKey="V"
|
||||
DefaultModifiers="Alt"/>
|
||||
<local:HotkeyItem x:Name="ExitHotkey"
|
||||
Title="退出"
|
||||
Description="退出当前模式或应用程序"
|
||||
DefaultKey="Escape"
|
||||
DefaultModifiers="None"/>
|
||||
</ui:SimpleStackPanel>
|
||||
</GroupBox>
|
||||
</ui:SimpleStackPanel>
|
||||
</ui:SimpleStackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<Border Height="60" Background="#F8F9FA" CornerRadius="0,0,10,10" VerticalAlignment="Bottom">
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,20,0">
|
||||
<Button x:Name="BtnResetToDefault"
|
||||
Content="重置为默认"
|
||||
Width="100"
|
||||
Height="35"
|
||||
Margin="0,0,10,0"
|
||||
Click="BtnResetToDefault_Click"/>
|
||||
<Button x:Name="BtnSave"
|
||||
Content="保存设置"
|
||||
Width="100"
|
||||
Height="35"
|
||||
Background="#0066BF"
|
||||
Foreground="White"
|
||||
Click="BtnSave_Click"/>
|
||||
</ui:SimpleStackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
||||
@@ -0,0 +1,357 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Ink_Canvas.Helpers;
|
||||
|
||||
namespace Ink_Canvas.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// 快捷键设置窗口
|
||||
/// </summary>
|
||||
public partial class HotkeySettingsWindow : Window
|
||||
{
|
||||
#region Private Fields
|
||||
private readonly MainWindow _mainWindow;
|
||||
private readonly GlobalHotkeyManager _hotkeyManager;
|
||||
private readonly Dictionary<string, HotkeyItem> _hotkeyItems;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public HotkeySettingsWindow(MainWindow mainWindow, GlobalHotkeyManager hotkeyManager)
|
||||
{
|
||||
InitializeComponent();
|
||||
_mainWindow = mainWindow;
|
||||
_hotkeyManager = hotkeyManager;
|
||||
_hotkeyItems = new Dictionary<string, HotkeyItem>();
|
||||
|
||||
// 隐藏主窗口的设置页面
|
||||
HideMainWindowSettings();
|
||||
InitializeHotkeyItems();
|
||||
LoadCurrentHotkeys();
|
||||
SetupEventHandlers();
|
||||
|
||||
// 注册窗口关闭事件
|
||||
this.Closed += HotkeySettingsWindow_Closed;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void InitializeHotkeyItems()
|
||||
{
|
||||
// 初始化快捷键项
|
||||
_hotkeyItems["Undo"] = UndoHotkey;
|
||||
_hotkeyItems["Redo"] = RedoHotkey;
|
||||
_hotkeyItems["Clear"] = ClearHotkey;
|
||||
_hotkeyItems["Paste"] = PasteHotkey;
|
||||
_hotkeyItems["SelectTool"] = SelectToolHotkey;
|
||||
_hotkeyItems["DrawTool"] = DrawToolHotkey;
|
||||
_hotkeyItems["EraserTool"] = EraserToolHotkey;
|
||||
_hotkeyItems["BlackboardTool"] = BlackboardToolHotkey;
|
||||
_hotkeyItems["QuitDrawTool"] = QuitDrawToolHotkey;
|
||||
_hotkeyItems["Pen1"] = Pen1Hotkey;
|
||||
_hotkeyItems["Pen2"] = Pen2Hotkey;
|
||||
_hotkeyItems["Pen3"] = Pen3Hotkey;
|
||||
_hotkeyItems["Pen4"] = Pen4Hotkey;
|
||||
_hotkeyItems["Pen5"] = Pen5Hotkey;
|
||||
_hotkeyItems["DrawLine"] = DrawLineHotkey;
|
||||
_hotkeyItems["Screenshot"] = ScreenshotHotkey;
|
||||
_hotkeyItems["Hide"] = HideHotkey;
|
||||
_hotkeyItems["Exit"] = ExitHotkey;
|
||||
}
|
||||
|
||||
private void LoadCurrentHotkeys()
|
||||
{
|
||||
try
|
||||
{
|
||||
var registeredHotkeys = _hotkeyManager.GetRegisteredHotkeys();
|
||||
foreach (var hotkey in registeredHotkeys)
|
||||
{
|
||||
if (_hotkeyItems.TryGetValue(hotkey.Name, out var hotkeyItem))
|
||||
{
|
||||
hotkeyItem.SetCurrentHotkey(hotkey.Key, hotkey.Modifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"加载当前快捷键时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupEventHandlers()
|
||||
{
|
||||
// 为每个快捷键项设置事件处理器
|
||||
foreach (var hotkeyItem in _hotkeyItems.Values)
|
||||
{
|
||||
hotkeyItem.HotkeyChanged += OnHotkeyChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHotkeyChanged(object sender, HotkeyChangedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查快捷键冲突
|
||||
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;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void UpdateHotkeyInManager(string hotkeyName, Key key, ModifierKeys modifiers)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 根据快捷键名称获取对应的动作
|
||||
var action = GetActionForHotkey(hotkeyName);
|
||||
if (action != null)
|
||||
{
|
||||
_hotkeyManager.RegisterHotkey(hotkeyName, key, modifiers, action);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"更新快捷键管理器时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private Action GetActionForHotkey(string hotkeyName)
|
||||
{
|
||||
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 "Hide":
|
||||
return () => _mainWindow.SymbolIconEmoji_MouseUp(null, null);
|
||||
case "Exit":
|
||||
return () => _mainWindow.KeyExit(null, null);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换到指定笔类型
|
||||
/// </summary>
|
||||
/// <param name="penTypeIndex">笔类型索引</param>
|
||||
private void SwitchToPenType(int penTypeIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 通过反射访问主窗口的penType字段
|
||||
var penTypeField = _mainWindow.GetType().GetField("penType",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
|
||||
if (penTypeField != null)
|
||||
{
|
||||
penTypeField.SetValue(_mainWindow, penTypeIndex);
|
||||
|
||||
// 调用CheckPenTypeUIState方法更新UI状态
|
||||
var checkPenTypeMethod = _mainWindow.GetType().GetMethod("CheckPenTypeUIState",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
|
||||
if (checkPenTypeMethod != null)
|
||||
{
|
||||
checkPenTypeMethod.Invoke(_mainWindow, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"切换到笔类型{penTypeIndex}时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MainWindow Settings Management
|
||||
/// <summary>
|
||||
/// 隐藏主窗口的设置页面
|
||||
/// </summary>
|
||||
private void HideMainWindowSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 通过反射访问主窗口的设置面板
|
||||
var settingsBorder = _mainWindow.GetType().GetField("BorderSettings",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(_mainWindow) as System.Windows.Controls.Border;
|
||||
|
||||
if (settingsBorder != null)
|
||||
{
|
||||
settingsBorder.Visibility = System.Windows.Visibility.Collapsed;
|
||||
}
|
||||
|
||||
// 隐藏设置蒙版
|
||||
var settingsMask = _mainWindow.GetType().GetField("BorderSettingsMask",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(_mainWindow) as System.Windows.Controls.Border;
|
||||
|
||||
if (settingsMask != null)
|
||||
{
|
||||
settingsMask.Visibility = System.Windows.Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"隐藏主窗口设置页面时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示主窗口的设置页面
|
||||
/// </summary>
|
||||
private void ShowMainWindowSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 通过反射访问主窗口的设置面板
|
||||
var settingsBorder = _mainWindow.GetType().GetField("BorderSettings",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(_mainWindow) as System.Windows.Controls.Border;
|
||||
|
||||
if (settingsBorder != null)
|
||||
{
|
||||
settingsBorder.Visibility = System.Windows.Visibility.Visible;
|
||||
}
|
||||
|
||||
// 显示设置蒙版
|
||||
var settingsMask = _mainWindow.GetType().GetField("BorderSettingsMask",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(_mainWindow) as System.Windows.Controls.Border;
|
||||
|
||||
if (settingsMask != null)
|
||||
{
|
||||
settingsMask.Visibility = System.Windows.Visibility.Visible;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"显示主窗口设置页面时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Window Event Handlers
|
||||
/// <summary>
|
||||
/// 窗口关闭事件处理
|
||||
/// </summary>
|
||||
private void HotkeySettingsWindow_Closed(object sender, EventArgs e)
|
||||
{
|
||||
// 恢复主窗口设置页面的显示
|
||||
ShowMainWindowSettings();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
private void BtnClose_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void BtnResetToDefault_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = MessageBox.Show("确定要重置所有快捷键为默认设置吗?",
|
||||
"确认重置", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
// 重置为默认快捷键
|
||||
_hotkeyManager.RegisterDefaultHotkeys();
|
||||
|
||||
// 更新UI显示
|
||||
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
|
||||
{
|
||||
// 保存快捷键配置
|
||||
_hotkeyManager.SaveHotkeysToSettings();
|
||||
|
||||
MessageBox.Show("快捷键设置已保存。", "保存成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"保存快捷键设置时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
MessageBox.Show($"保存快捷键设置时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Hotkey Changed Event Args
|
||||
/// <summary>
|
||||
/// 快捷键变更事件参数
|
||||
/// </summary>
|
||||
public class HotkeyChangedEventArgs : EventArgs
|
||||
{
|
||||
public string HotkeyName { get; set; }
|
||||
public Key Key { get; set; }
|
||||
public ModifierKeys Modifiers { get; set; }
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user