fix:issue #202
This commit is contained in:
@@ -5,12 +5,15 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace Ink_Canvas.Helpers
|
namespace Ink_Canvas.Helpers
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 全局快捷键管理器 - 使用NHotkey库实现全局快捷键功能
|
/// 全局快捷键管理器 - 使用NHotkey库实现全局快捷键功能
|
||||||
|
/// 支持多屏幕环境下的智能热键注册,避免影响其他屏幕的复制粘贴功能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GlobalHotkeyManager : IDisposable
|
public class GlobalHotkeyManager : IDisposable
|
||||||
{
|
{
|
||||||
@@ -19,6 +22,16 @@ namespace Ink_Canvas.Helpers
|
|||||||
private readonly MainWindow _mainWindow;
|
private readonly MainWindow _mainWindow;
|
||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
private bool _hotkeysShouldBeRegistered = true; // 启动时注册热键
|
private bool _hotkeysShouldBeRegistered = true; // 启动时注册热键
|
||||||
|
|
||||||
|
// 多屏幕支持相关字段
|
||||||
|
private Screen _currentScreen;
|
||||||
|
private bool _isMultiScreenMode = false;
|
||||||
|
private bool _enableScreenSpecificHotkeys = true; // 是否启用基于屏幕的热键注册
|
||||||
|
|
||||||
|
// 智能热键管理相关字段
|
||||||
|
private bool _isWindowFocused = false;
|
||||||
|
private bool _isMouseOverWindow = false;
|
||||||
|
private System.Windows.Threading.DispatcherTimer _mousePositionTimer;
|
||||||
|
|
||||||
// 配置文件路径
|
// 配置文件路径
|
||||||
private static readonly string HotkeyConfigFile = Path.Combine(App.RootPath, "Configs", "HotkeyConfig.json");
|
private static readonly string HotkeyConfigFile = Path.Combine(App.RootPath, "Configs", "HotkeyConfig.json");
|
||||||
@@ -31,6 +44,9 @@ namespace Ink_Canvas.Helpers
|
|||||||
_registeredHotkeys = new Dictionary<string, HotkeyInfo>();
|
_registeredHotkeys = new Dictionary<string, HotkeyInfo>();
|
||||||
_hotkeysShouldBeRegistered = true; // 启动时注册热键
|
_hotkeysShouldBeRegistered = true; // 启动时注册热键
|
||||||
|
|
||||||
|
// 初始化多屏幕支持
|
||||||
|
InitializeMultiScreenSupport();
|
||||||
|
|
||||||
// 启动时确保配置文件存在
|
// 启动时确保配置文件存在
|
||||||
EnsureConfigFileExists();
|
EnsureConfigFileExists();
|
||||||
}
|
}
|
||||||
@@ -52,6 +68,12 @@ namespace Ink_Canvas.Helpers
|
|||||||
if (_isDisposed)
|
if (_isDisposed)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// 检查是否应该注册热键(基于屏幕和模式)
|
||||||
|
if (!ShouldRegisterHotkeys())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 如果快捷键已存在,先注销
|
// 如果快捷键已存在,先注销
|
||||||
if (_registeredHotkeys.ContainsKey(hotkeyName))
|
if (_registeredHotkeys.ContainsKey(hotkeyName))
|
||||||
{
|
{
|
||||||
@@ -85,7 +107,10 @@ namespace Ink_Canvas.Helpers
|
|||||||
});
|
});
|
||||||
|
|
||||||
_registeredHotkeys[hotkeyName] = hotkeyInfo;
|
_registeredHotkeys[hotkeyName] = hotkeyInfo;
|
||||||
// 成功注册全局快捷键
|
|
||||||
|
// 记录注册信息
|
||||||
|
var screenInfo = _isMultiScreenMode ? $" (屏幕: {_currentScreen?.DeviceName})" : "";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -179,7 +204,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
if (!File.Exists(HotkeyConfigFile))
|
if (!File.Exists(HotkeyConfigFile))
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile("快捷键配置文件不存在");
|
|
||||||
return new List<HotkeyInfo>();
|
return new List<HotkeyInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +236,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LogHelper.WriteLogToFile($"从配置文件读取到 {hotkeyList.Count} 个快捷键信息");
|
|
||||||
return hotkeyList;
|
return hotkeyList;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -287,7 +310,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
if (!File.Exists(HotkeyConfigFile))
|
if (!File.Exists(HotkeyConfigFile))
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"快捷键配置文件不存在: {HotkeyConfigFile}", LogHelper.LogType.Warning);
|
LogHelper.WriteLogToFile($"快捷键配置文件不存在: {HotkeyConfigFile}", LogHelper.LogType.Warning);
|
||||||
LogHelper.WriteLogToFile("配置文件不存在,创建默认配置文件并注册默认快捷键");
|
|
||||||
CreateDefaultConfigFile();
|
CreateDefaultConfigFile();
|
||||||
RegisterDefaultHotkeys();
|
RegisterDefaultHotkeys();
|
||||||
_hotkeysShouldBeRegistered = true;
|
_hotkeysShouldBeRegistered = true;
|
||||||
@@ -299,7 +321,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
// 成功从配置文件加载快捷键设置
|
// 成功从配置文件加载快捷键设置
|
||||||
_hotkeysShouldBeRegistered = true;
|
_hotkeysShouldBeRegistered = true;
|
||||||
LogHelper.WriteLogToFile("成功从配置文件加载快捷键设置");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -322,11 +343,9 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile("开始保存快捷键配置到配置文件", LogHelper.LogType.Event);
|
|
||||||
|
|
||||||
if (SaveHotkeysToConfigFile())
|
if (SaveHotkeysToConfigFile())
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile("快捷键配置已成功保存到配置文件", LogHelper.LogType.Event);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -350,10 +369,18 @@ namespace Ink_Canvas.Helpers
|
|||||||
if (!_hotkeysShouldBeRegistered)
|
if (!_hotkeysShouldBeRegistered)
|
||||||
{
|
{
|
||||||
_hotkeysShouldBeRegistered = true;
|
_hotkeysShouldBeRegistered = true;
|
||||||
LogHelper.WriteLogToFile("启用快捷键注册功能");
|
|
||||||
|
|
||||||
// 立即加载快捷键设置
|
// 启动鼠标位置监控定时器
|
||||||
LoadHotkeysFromSettings();
|
if (_isMultiScreenMode && _enableScreenSpecificHotkeys && _mousePositionTimer != null)
|
||||||
|
{
|
||||||
|
_mousePositionTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据上下文决定是否立即加载快捷键
|
||||||
|
if (ShouldEnableHotkeysBasedOnContext())
|
||||||
|
{
|
||||||
|
LoadHotkeysFromSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -377,12 +404,17 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
_hotkeysShouldBeRegistered = false;
|
_hotkeysShouldBeRegistered = false;
|
||||||
|
|
||||||
|
// 停止鼠标位置监控定时器
|
||||||
|
if (_mousePositionTimer != null && _mousePositionTimer.IsEnabled)
|
||||||
|
{
|
||||||
|
_mousePositionTimer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
// 注销所有快捷键
|
// 注销所有快捷键
|
||||||
UnregisterAllHotkeys();
|
UnregisterAllHotkeys();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile("快捷键注册功能已经禁用");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -407,7 +439,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
// 如果设置允许,则在鼠标模式下也启用快捷键
|
// 如果设置允许,则在鼠标模式下也启用快捷键
|
||||||
EnableHotkeyRegistration();
|
EnableHotkeyRegistration();
|
||||||
LogHelper.WriteLogToFile("切换到鼠标模式,但根据设置保持快捷键启用");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -455,7 +486,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"成功更新快捷键 {hotkeyName}: {modifiers}+{key}", LogHelper.LogType.Event);
|
|
||||||
// 自动保存配置
|
// 自动保存配置
|
||||||
SaveHotkeysToSettings();
|
SaveHotkeysToSettings();
|
||||||
}
|
}
|
||||||
@@ -468,9 +498,418 @@ namespace Ink_Canvas.Helpers
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 启用基于屏幕的热键注册
|
||||||
|
/// </summary>
|
||||||
|
public void EnableScreenSpecificHotkeys()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_enableScreenSpecificHotkeys = true;
|
||||||
|
|
||||||
|
// 如果当前在多屏幕环境下,刷新热键注册
|
||||||
|
if (_isMultiScreenMode)
|
||||||
|
{
|
||||||
|
RefreshHotkeysForCurrentScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"启用基于屏幕的热键注册时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 禁用基于屏幕的热键注册
|
||||||
|
/// </summary>
|
||||||
|
public void DisableScreenSpecificHotkeys()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_enableScreenSpecificHotkeys = false;
|
||||||
|
|
||||||
|
// 重新注册热键(全局模式)
|
||||||
|
if (_hotkeysShouldBeRegistered)
|
||||||
|
{
|
||||||
|
RefreshHotkeysForCurrentScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"禁用基于屏幕的热键注册时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前屏幕信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>当前屏幕信息</returns>
|
||||||
|
public string GetCurrentScreenInfo()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_isMultiScreenMode && _currentScreen != null)
|
||||||
|
{
|
||||||
|
return $"多屏幕环境 - 当前屏幕: {_currentScreen.DeviceName} ({_currentScreen.Bounds.Width}x{_currentScreen.Bounds.Height})";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "单屏幕环境";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"获取当前屏幕信息时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
return "无法获取屏幕信息";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查是否启用了基于屏幕的热键注册
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>是否启用</returns>
|
||||||
|
public bool IsScreenSpecificHotkeysEnabled()
|
||||||
|
{
|
||||||
|
return _enableScreenSpecificHotkeys && _isMultiScreenMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 手动刷新当前屏幕的热键注册
|
||||||
|
/// </summary>
|
||||||
|
public void RefreshCurrentScreenHotkeys()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RefreshHotkeysForCurrentScreen();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"刷新当前屏幕热键时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Helper Methods
|
#region Private Helper Methods
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化多屏幕支持
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeMultiScreenSupport()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 检测是否有多个屏幕
|
||||||
|
_isMultiScreenMode = ScreenDetectionHelper.HasMultipleScreens();
|
||||||
|
|
||||||
|
if (_isMultiScreenMode)
|
||||||
|
{
|
||||||
|
// 获取当前窗口所在的屏幕
|
||||||
|
_currentScreen = ScreenDetectionHelper.GetWindowScreen(_mainWindow);
|
||||||
|
|
||||||
|
// 监听窗口位置变化事件
|
||||||
|
_mainWindow.LocationChanged += OnWindowLocationChanged;
|
||||||
|
|
||||||
|
// 初始化智能热键管理
|
||||||
|
InitializeSmartHotkeyManagement();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_currentScreen = ScreenDetectionHelper.GetPrimaryScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"初始化多屏幕支持时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
_isMultiScreenMode = false;
|
||||||
|
_currentScreen = ScreenDetectionHelper.GetPrimaryScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化智能热键管理
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeSmartHotkeyManagement()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 监听窗口焦点事件
|
||||||
|
_mainWindow.GotFocus += OnWindowGotFocus;
|
||||||
|
_mainWindow.LostFocus += OnWindowLostFocus;
|
||||||
|
|
||||||
|
// 监听鼠标进入/离开事件
|
||||||
|
_mainWindow.MouseEnter += OnMouseEnterWindow;
|
||||||
|
_mainWindow.MouseLeave += OnMouseLeaveWindow;
|
||||||
|
|
||||||
|
// 初始化鼠标位置监控定时器
|
||||||
|
_mousePositionTimer = new System.Windows.Threading.DispatcherTimer();
|
||||||
|
_mousePositionTimer.Interval = TimeSpan.FromMilliseconds(500); // 每500ms检查一次
|
||||||
|
_mousePositionTimer.Tick += OnMousePositionTimerTick;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"初始化热键管理时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 窗口位置变化事件处理
|
||||||
|
/// </summary>
|
||||||
|
private void OnWindowLocationChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_isMultiScreenMode || !_enableScreenSpecificHotkeys)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var newScreen = ScreenDetectionHelper.GetWindowScreen(_mainWindow);
|
||||||
|
if (newScreen != null && newScreen != _currentScreen)
|
||||||
|
{
|
||||||
|
_currentScreen = newScreen;
|
||||||
|
|
||||||
|
// 重新注册热键以适应新屏幕
|
||||||
|
RefreshHotkeysForCurrentScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"处理窗口位置变化时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 为当前屏幕刷新热键注册
|
||||||
|
/// </summary>
|
||||||
|
private void RefreshHotkeysForCurrentScreen()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_hotkeysShouldBeRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 注销所有现有热键
|
||||||
|
UnregisterAllHotkeys();
|
||||||
|
|
||||||
|
// 重新注册热键
|
||||||
|
LoadHotkeysFromSettings();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"刷新当前屏幕热键时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 窗口获得焦点事件处理
|
||||||
|
/// </summary>
|
||||||
|
private void OnWindowGotFocus(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_isWindowFocused = true;
|
||||||
|
UpdateHotkeyStateBasedOnContext();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"处理窗口获得焦点事件时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 窗口失去焦点事件处理
|
||||||
|
/// </summary>
|
||||||
|
private void OnWindowLostFocus(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_isWindowFocused = false;
|
||||||
|
UpdateHotkeyStateBasedOnContext();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"处理窗口失去焦点事件时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 鼠标进入窗口事件处理
|
||||||
|
/// </summary>
|
||||||
|
private void OnMouseEnterWindow(object sender, System.Windows.Input.MouseEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_isMouseOverWindow = true;
|
||||||
|
UpdateHotkeyStateBasedOnContext();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"处理鼠标进入窗口事件时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 鼠标离开窗口事件处理
|
||||||
|
/// </summary>
|
||||||
|
private void OnMouseLeaveWindow(object sender, System.Windows.Input.MouseEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_isMouseOverWindow = false;
|
||||||
|
UpdateHotkeyStateBasedOnContext();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"处理鼠标离开窗口事件时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 鼠标位置定时器事件处理
|
||||||
|
/// </summary>
|
||||||
|
private void OnMousePositionTimerTick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_isMultiScreenMode || !_enableScreenSpecificHotkeys)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 检查鼠标是否在当前窗口所在的屏幕上
|
||||||
|
var mousePosition = System.Windows.Forms.Control.MousePosition;
|
||||||
|
var currentScreen = Screen.FromPoint(mousePosition);
|
||||||
|
|
||||||
|
// 无论屏幕是否变化,都检查热键状态
|
||||||
|
// 这样可以确保热键状态始终与当前上下文保持一致
|
||||||
|
bool shouldEnableHotkeys = ShouldEnableHotkeysBasedOnContext();
|
||||||
|
bool currentlyHasHotkeys = _registeredHotkeys.Count > 0;
|
||||||
|
|
||||||
|
if (shouldEnableHotkeys && !currentlyHasHotkeys)
|
||||||
|
{
|
||||||
|
UpdateHotkeyStateBasedOnContext();
|
||||||
|
}
|
||||||
|
else if (!shouldEnableHotkeys && currentlyHasHotkeys)
|
||||||
|
{
|
||||||
|
UpdateHotkeyStateBasedOnContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"处理鼠标位置定时器事件时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据上下文更新热键状态
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateHotkeyStateBasedOnContext()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_hotkeysShouldBeRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool shouldEnableHotkeys = ShouldEnableHotkeysBasedOnContext();
|
||||||
|
|
||||||
|
if (shouldEnableHotkeys)
|
||||||
|
{
|
||||||
|
// 如果热键未注册,则注册
|
||||||
|
if (_registeredHotkeys.Count == 0)
|
||||||
|
{
|
||||||
|
LoadHotkeysFromSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 如果热键已注册,则注销(与鼠标模式禁用保持一致)
|
||||||
|
if (_registeredHotkeys.Count > 0)
|
||||||
|
{
|
||||||
|
UnregisterAllHotkeys();
|
||||||
|
|
||||||
|
// 注意:这里不设置 _hotkeysShouldBeRegistered = false
|
||||||
|
// 因为我们需要保持热键系统的启用状态,只是暂时注销热键
|
||||||
|
// 这样当上下文变化时,热键可以重新注册
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"根据上下文更新热键状态时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查是否应该注册热键(基于屏幕和模式)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>是否应该注册热键</returns>
|
||||||
|
private bool ShouldRegisterHotkeys()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 如果禁用热键注册,则不注册
|
||||||
|
if (!_hotkeysShouldBeRegistered)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 如果启用基于屏幕的热键注册
|
||||||
|
if (_enableScreenSpecificHotkeys && _isMultiScreenMode)
|
||||||
|
{
|
||||||
|
return ShouldEnableHotkeysBasedOnContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"检查是否应该注册热键时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
return true; // 出错时默认注册
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据上下文检查是否应该启用热键
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>是否应该启用热键</returns>
|
||||||
|
private bool ShouldEnableHotkeysBasedOnContext()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 策略1:鼠标在窗口上时启用热键(最高优先级)
|
||||||
|
if (_isMouseOverWindow)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 策略2:在多屏幕环境下,检查鼠标是否在当前窗口所在的屏幕上
|
||||||
|
if (_isMultiScreenMode)
|
||||||
|
{
|
||||||
|
var mousePosition = System.Windows.Forms.Control.MousePosition;
|
||||||
|
var mouseScreen = Screen.FromPoint(mousePosition);
|
||||||
|
|
||||||
|
if (mouseScreen == _currentScreen)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 策略3:单屏幕环境下,窗口有焦点时启用热键
|
||||||
|
if (_isWindowFocused)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认情况:禁用热键
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"检查是否应该启用热键时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
return true; // 出错时默认启用
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 切换到指定笔类型
|
/// 切换到指定笔类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -513,7 +952,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
// 如果配置文件不存在,创建默认配置文件
|
// 如果配置文件不存在,创建默认配置文件
|
||||||
if (!File.Exists(HotkeyConfigFile))
|
if (!File.Exists(HotkeyConfigFile))
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"快捷键配置文件不存在,创建默认配置文件: {HotkeyConfigFile}", LogHelper.LogType.Event);
|
|
||||||
CreateDefaultConfigFile();
|
CreateDefaultConfigFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -579,7 +1017,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
// 写入配置文件
|
// 写入配置文件
|
||||||
File.WriteAllText(HotkeyConfigFile, jsonContent, Encoding.UTF8);
|
File.WriteAllText(HotkeyConfigFile, jsonContent, Encoding.UTF8);
|
||||||
|
|
||||||
LogHelper.WriteLogToFile($"已创建默认快捷键配置文件: {HotkeyConfigFile}", LogHelper.LogType.Event);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -643,7 +1080,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogHelper.WriteLogToFile($"成功加载 {successCount}/{config.Hotkeys.Count} 个快捷键配置", LogHelper.LogType.Event);
|
|
||||||
if (successCount > 0)
|
if (successCount > 0)
|
||||||
{
|
{
|
||||||
_hotkeysShouldBeRegistered = true;
|
_hotkeysShouldBeRegistered = true;
|
||||||
@@ -702,7 +1138,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
// 直接写入原文件,覆盖原有内容
|
// 直接写入原文件,覆盖原有内容
|
||||||
File.WriteAllText(HotkeyConfigFile, jsonContent, Encoding.UTF8);
|
File.WriteAllText(HotkeyConfigFile, jsonContent, Encoding.UTF8);
|
||||||
|
|
||||||
LogHelper.WriteLogToFile($"快捷键配置已保存到: {HotkeyConfigFile}", LogHelper.LogType.Event);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -908,6 +1343,29 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
if (!_isDisposed)
|
if (!_isDisposed)
|
||||||
{
|
{
|
||||||
|
// 注销所有快捷键
|
||||||
|
UnregisterAllHotkeys();
|
||||||
|
|
||||||
|
// 停止定时器
|
||||||
|
if (_mousePositionTimer != null)
|
||||||
|
{
|
||||||
|
_mousePositionTimer.Stop();
|
||||||
|
_mousePositionTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除事件监听器
|
||||||
|
if (_mainWindow != null)
|
||||||
|
{
|
||||||
|
if (_isMultiScreenMode)
|
||||||
|
{
|
||||||
|
_mainWindow.LocationChanged -= OnWindowLocationChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
_mainWindow.GotFocus -= OnWindowGotFocus;
|
||||||
|
_mainWindow.LostFocus -= OnWindowLostFocus;
|
||||||
|
_mainWindow.MouseEnter -= OnMouseEnterWindow;
|
||||||
|
_mainWindow.MouseLeave -= OnMouseLeaveWindow;
|
||||||
|
}
|
||||||
|
|
||||||
_isDisposed = true;
|
_isDisposed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Windows.Interop;
|
||||||
|
using Point = System.Windows.Point;
|
||||||
|
|
||||||
|
namespace Ink_Canvas.Helpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 屏幕检测帮助类 - 用于检测窗口所在的屏幕和屏幕信息
|
||||||
|
/// </summary>
|
||||||
|
public static class ScreenDetectionHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取窗口所在的屏幕
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="window">要检测的窗口</param>
|
||||||
|
/// <returns>窗口所在的屏幕,如果无法检测则返回主屏幕</returns>
|
||||||
|
public static Screen GetWindowScreen(Window window)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (window == null)
|
||||||
|
return Screen.PrimaryScreen;
|
||||||
|
|
||||||
|
// 获取窗口的句柄
|
||||||
|
var hwndSource = PresentationSource.FromVisual(window) as HwndSource;
|
||||||
|
if (hwndSource == null)
|
||||||
|
return Screen.PrimaryScreen;
|
||||||
|
|
||||||
|
// 获取窗口在屏幕上的位置
|
||||||
|
var windowRect = GetWindowScreenBounds(window);
|
||||||
|
|
||||||
|
// 查找与窗口重叠最多的屏幕
|
||||||
|
Screen targetScreen = null;
|
||||||
|
double maxIntersection = 0;
|
||||||
|
|
||||||
|
foreach (var screen in Screen.AllScreens)
|
||||||
|
{
|
||||||
|
var intersection = Rectangle.Intersect(windowRect, screen.Bounds);
|
||||||
|
if (intersection.Width * intersection.Height > maxIntersection)
|
||||||
|
{
|
||||||
|
maxIntersection = intersection.Width * intersection.Height;
|
||||||
|
targetScreen = screen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetScreen ?? Screen.PrimaryScreen;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"检测窗口屏幕时出错: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
return Screen.PrimaryScreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取窗口在屏幕坐标系中的边界
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="window">要检测的窗口</param>
|
||||||
|
/// <returns>窗口的屏幕边界</returns>
|
||||||
|
private static Rectangle GetWindowScreenBounds(Window window)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 获取窗口左上角在屏幕上的位置
|
||||||
|
var topLeft = window.PointToScreen(new Point(0, 0));
|
||||||
|
|
||||||
|
// 获取窗口右下角在屏幕上的位置
|
||||||
|
var bottomRight = window.PointToScreen(new Point(window.ActualWidth, window.ActualHeight));
|
||||||
|
|
||||||
|
return new Rectangle(
|
||||||
|
(int)topLeft.X,
|
||||||
|
(int)topLeft.Y,
|
||||||
|
(int)(bottomRight.X - topLeft.X),
|
||||||
|
(int)(bottomRight.Y - topLeft.Y));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// 如果无法获取精确位置,返回窗口的Left和Top
|
||||||
|
return new Rectangle(
|
||||||
|
(int)window.Left,
|
||||||
|
(int)window.Top,
|
||||||
|
(int)window.Width,
|
||||||
|
(int)window.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查是否有多个屏幕
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>如果有多个屏幕返回true,否则返回false</returns>
|
||||||
|
public static bool HasMultipleScreens()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Screen.AllScreens.Length > 1;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取主屏幕
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>主屏幕</returns>
|
||||||
|
public static Screen GetPrimaryScreen()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Screen.PrimaryScreen;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有屏幕信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>所有屏幕的数组</returns>
|
||||||
|
public static Screen[] GetAllScreens()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Screen.AllScreens;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new Screen[] { Screen.PrimaryScreen };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查窗口是否在主屏幕上
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="window">要检查的窗口</param>
|
||||||
|
/// <returns>如果窗口在主屏幕上返回true,否则返回false</returns>
|
||||||
|
public static bool IsWindowOnPrimaryScreen(Window window)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var windowScreen = GetWindowScreen(window);
|
||||||
|
return windowScreen == Screen.PrimaryScreen;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return true; // 出错时假设在主屏幕
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user