diff --git a/Ink Canvas/FloatingWindowInterceptorManager.cs b/Ink Canvas/FloatingWindowInterceptorManager.cs
new file mode 100644
index 00000000..3618f09f
--- /dev/null
+++ b/Ink Canvas/FloatingWindowInterceptorManager.cs
@@ -0,0 +1,393 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using Ink_Canvas.Helpers;
+
+namespace Ink_Canvas
+{
+ ///
+ /// 悬浮窗拦截管理器
+ ///
+ public class FloatingWindowInterceptorManager : IDisposable
+ {
+ #region 私有字段
+
+ private FloatingWindowInterceptor _interceptor;
+ private bool _isInitialized;
+ private bool _disposed;
+ private FloatingWindowInterceptorSettings _settings;
+
+ #endregion
+
+ #region 事件
+
+ public event EventHandler WindowIntercepted;
+ public event EventHandler WindowRestored;
+
+ #endregion
+
+ #region 公共属性
+
+ public bool IsEnabled => _interceptor != null && _settings != null && _settings.IsEnabled;
+ public bool IsRunning => _interceptor != null && _isInitialized;
+
+ #endregion
+
+ #region 公共方法
+
+ ///
+ /// 初始化拦截器
+ ///
+ public void Initialize(FloatingWindowInterceptorSettings settings)
+ {
+ if (_isInitialized) return;
+
+ try
+ {
+ _settings = settings ?? new FloatingWindowInterceptorSettings();
+ _interceptor = new FloatingWindowInterceptor();
+
+ // 订阅事件
+ _interceptor.WindowIntercepted += OnWindowIntercepted;
+ _interceptor.WindowRestored += OnWindowRestored;
+
+ // 应用配置
+ ApplySettings();
+
+ _isInitialized = true;
+
+ // 如果设置了自动启动,则启动拦截器
+ if (_settings.AutoStart && _settings.IsEnabled)
+ {
+ Start();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"初始化悬浮窗拦截器失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 启动拦截器
+ ///
+ public void Start()
+ {
+ if (!_isInitialized || _settings == null) return;
+
+ if (_interceptor == null) return;
+
+ try
+ {
+ _interceptor.Start(_settings.ScanIntervalMs);
+ LogHelper.WriteLogToFile("悬浮窗拦截器已启动", LogHelper.LogType.Event);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"启动悬浮窗拦截器失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 停止拦截器
+ ///
+ public void Stop()
+ {
+ if (_interceptor == null) return;
+
+ try
+ {
+ _interceptor.Stop();
+ LogHelper.WriteLogToFile("悬浮窗拦截器已停止", LogHelper.LogType.Event);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"停止悬浮窗拦截器失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 设置拦截规则
+ ///
+ public void SetInterceptRule(FloatingWindowInterceptor.InterceptType type, bool enabled)
+ {
+ if (_interceptor == null || _settings == null) return;
+
+ try
+ {
+ _interceptor.SetInterceptRule(type, enabled);
+
+ // 更新设置
+ var ruleName = type.ToString();
+ if (_settings.InterceptRules.ContainsKey(ruleName))
+ {
+ _settings.InterceptRules[ruleName] = enabled;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"设置拦截规则失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 获取拦截规则
+ ///
+ public FloatingWindowInterceptor.InterceptRule GetInterceptRule(FloatingWindowInterceptor.InterceptType type)
+ {
+ return _interceptor?.GetInterceptRule(type);
+ }
+
+ ///
+ /// 获取所有拦截规则
+ ///
+ public Dictionary GetAllRules()
+ {
+ return _interceptor?.GetAllRules() ?? new Dictionary();
+ }
+
+ ///
+ /// 手动扫描一次
+ ///
+ public void ScanOnce()
+ {
+ if (_interceptor == null) return;
+
+ try
+ {
+ _interceptor.ScanOnce();
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"手动扫描失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 调试:列出所有可见窗口
+ ///
+ public void DebugListAllWindows()
+ {
+ if (_interceptor == null)
+ {
+ LogHelper.WriteLogToFile("拦截器未初始化,无法进行调试", LogHelper.LogType.Warning);
+ return;
+ }
+
+ try
+ {
+ LogHelper.WriteLogToFile("开始调试扫描所有可见窗口...", LogHelper.LogType.Event);
+
+ // 直接调用扫描方法,在扫描过程中会输出调试信息
+ _interceptor.ScanOnce();
+
+ LogHelper.WriteLogToFile("调试扫描完成,请查看日志文件获取详细信息", LogHelper.LogType.Event);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"调试列出窗口失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 恢复所有被拦截的窗口
+ ///
+ public void RestoreAllWindows()
+ {
+ if (_interceptor == null) return;
+
+ try
+ {
+ _interceptor.RestoreAllWindows();
+ LogHelper.WriteLogToFile("已恢复所有被拦截的窗口", LogHelper.LogType.Event);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"恢复窗口失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 应用设置
+ ///
+ public void ApplySettings()
+ {
+ if (_interceptor == null || _settings == null) return;
+
+ try
+ {
+ // 应用拦截规则设置
+ foreach (var kvp in _settings.InterceptRules)
+ {
+ if (Enum.TryParse(kvp.Key, out var type))
+ {
+ _interceptor.SetInterceptRule(type, kvp.Value);
+ }
+ }
+
+ // 如果启用了拦截器,则启动
+ if (_settings.IsEnabled && !IsRunning)
+ {
+ Start();
+ }
+ // 如果禁用了拦截器,则停止
+ else if (!_settings.IsEnabled && IsRunning)
+ {
+ Stop();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"应用设置失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 更新扫描间隔
+ ///
+ public void UpdateScanInterval(int intervalMs)
+ {
+ if (_interceptor == null || _settings == null) return;
+
+ try
+ {
+ _settings.ScanIntervalMs = intervalMs;
+
+ // 如果正在运行,重启以应用新间隔
+ if (IsRunning)
+ {
+ Stop();
+ Start();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"更新扫描间隔失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 获取拦截统计信息
+ ///
+ public InterceptStatistics GetStatistics()
+ {
+ if (_interceptor == null || _settings == null) return new InterceptStatistics();
+
+ try
+ {
+ var rules = GetAllRules();
+ var enabledRules = rules.Count(r => r.Value.IsEnabled);
+ var totalRules = rules.Count;
+
+ return new InterceptStatistics
+ {
+ TotalRules = totalRules,
+ EnabledRules = enabledRules,
+ IsRunning = IsRunning,
+ ScanIntervalMs = _settings.ScanIntervalMs
+ };
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"获取统计信息失败: {ex.Message}", LogHelper.LogType.Error);
+ return new InterceptStatistics();
+ }
+ }
+
+ #endregion
+
+ #region 私有方法
+
+ private void OnWindowIntercepted(object sender, FloatingWindowInterceptor.WindowInterceptedEventArgs e)
+ {
+ try
+ {
+ // 记录日志
+ LogHelper.WriteLogToFile($"拦截窗口: {e.WindowTitle} ({e.InterceptType})", LogHelper.LogType.Event);
+
+ // 显示通知(如果启用)
+ if (_settings != null && _settings.ShowNotifications)
+ {
+ ShowNotification($"已拦截悬浮窗: {e.Rule.Description}");
+ }
+
+ // 触发事件
+ WindowIntercepted?.Invoke(this, e);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"处理窗口拦截事件失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ private void OnWindowRestored(object sender, FloatingWindowInterceptor.WindowRestoredEventArgs e)
+ {
+ try
+ {
+ // 记录日志
+ LogHelper.WriteLogToFile($"恢复窗口: {e.InterceptType}", LogHelper.LogType.Event);
+
+ // 触发事件
+ WindowRestored?.Invoke(this, e);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"处理窗口恢复事件失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ private void ShowNotification(string message)
+ {
+ try
+ {
+ // 这里可以集成系统通知或自定义通知
+ // 暂时使用调试输出
+ System.Diagnostics.Debug.WriteLine($"通知: {message}");
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"显示通知失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ #endregion
+
+ #region 辅助类
+
+ public class InterceptStatistics
+ {
+ public int TotalRules { get; set; }
+ public int EnabledRules { get; set; }
+ public bool IsRunning { get; set; }
+ public int ScanIntervalMs { get; set; }
+ }
+
+ #endregion
+
+ #region IDisposable
+
+ public void Dispose()
+ {
+ if (_disposed) return;
+
+ try
+ {
+ Stop();
+ _interceptor?.Dispose();
+ _interceptor = null;
+ _isInitialized = false;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"释放悬浮窗拦截器失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ finally
+ {
+ _disposed = true;
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/FloatingWindowInterceptor.cs b/Ink Canvas/Helpers/FloatingWindowInterceptor.cs
new file mode 100644
index 00000000..eedd031a
--- /dev/null
+++ b/Ink Canvas/Helpers/FloatingWindowInterceptor.cs
@@ -0,0 +1,775 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Threading;
+
+namespace Ink_Canvas.Helpers
+{
+ ///
+ /// 悬浮窗拦截器 - 检测和隐藏指定的悬浮窗
+ ///
+ public class FloatingWindowInterceptor : IDisposable
+ {
+ #region Windows API Declarations
+
+ [DllImport("user32.dll")]
+ private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
+
+ [DllImport("user32.dll")]
+ private static extern bool IsWindowVisible(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
+
+ [DllImport("user32.dll")]
+ private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
+
+ [DllImport("user32.dll")]
+ private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
+
+ [DllImport("user32.dll")]
+ private static extern bool IsIconic(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
+
+ [DllImport("user32.dll")]
+ private static extern uint GetWindowLong(IntPtr hWnd, int nIndex);
+
+ [DllImport("user32.dll")]
+ private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
+
+ [DllImport("user32.dll")]
+ private static extern bool IsWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ private static extern bool GetWindowRect(IntPtr hWnd, out ForegroundWindowInfo.RECT lpRect);
+
+ [DllImport("kernel32.dll")]
+ private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
+
+ [DllImport("kernel32.dll")]
+ private static extern bool CloseHandle(IntPtr hObject);
+
+ [DllImport("kernel32.dll")]
+ private static extern int GetProcessImageFileName(IntPtr hProcess, StringBuilder lpImageFileName, int nSize);
+
+ private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
+
+ private const int SW_HIDE = 0;
+ private const int SW_SHOW = 1;
+ private const int SW_MINIMIZE = 6;
+ private const int SW_RESTORE = 9;
+
+ private const int GWL_EXSTYLE = -20;
+ private const uint WS_EX_TOOLWINDOW = 0x00000080;
+ private const uint WS_EX_APPWINDOW = 0x00040000;
+
+ private const uint SWP_NOMOVE = 0x0002;
+ private const uint SWP_NOSIZE = 0x0001;
+ private const uint SWP_NOZORDER = 0x0004;
+ private const uint SWP_HIDEWINDOW = 0x0080;
+
+ private const uint PROCESS_QUERY_INFORMATION = 0x0400;
+ private const uint PROCESS_VM_READ = 0x0010;
+
+ #endregion
+
+ #region 拦截规则定义
+
+ ///
+ /// 拦截规则类型
+ ///
+ public enum InterceptType
+ {
+ ///
+ /// 希沃白板3 桌面悬浮窗
+ ///
+ SeewoWhiteboard3Floating,
+ ///
+ /// 希沃白板5 桌面悬浮窗
+ ///
+ SeewoWhiteboard5Floating,
+ ///
+ /// 希沃白板5C 桌面悬浮窗
+ ///
+ SeewoWhiteboard5CFloating,
+ ///
+ /// 希沃品课教师端 桌面悬浮窗
+ ///
+ SeewoPincoSideBarFloating,
+ ///
+ /// 希沃品课教师端 画笔悬浮窗(包括PPT控件)
+ ///
+ SeewoPincoDrawingFloating,
+ ///
+ /// 希沃PPT小工具
+ ///
+ SeewoPPTFloating,
+ ///
+ /// AiClass 桌面悬浮窗
+ ///
+ AiClassFloating,
+ ///
+ /// 鸿合屏幕书写
+ ///
+ HiteAnnotationFloating,
+ ///
+ /// 畅言智慧课堂 桌面悬浮窗
+ ///
+ ChangYanFloating,
+ ///
+ /// 畅言智慧课堂 PPT悬浮窗
+ ///
+ ChangYanPptFloating,
+ ///
+ /// 天喻教育云互动课堂 桌面悬浮窗(包括PPT控件)
+ ///
+ IntelligentClassFloating,
+ ///
+ /// 希沃桌面 画笔悬浮窗
+ ///
+ SeewoDesktopAnnotationFloating,
+ ///
+ /// 希沃桌面 侧栏悬浮窗
+ ///
+ SeewoDesktopSideBarFloating
+ }
+
+ ///
+ /// 拦截规则
+ ///
+ public class InterceptRule
+ {
+ public InterceptType Type { get; set; }
+ public string ProcessName { get; set; }
+ public string WindowTitlePattern { get; set; }
+ public string ClassNamePattern { get; set; }
+ public bool IsEnabled { get; set; }
+ public bool RequiresAdmin { get; set; }
+ public string Description { get; set; }
+ }
+
+ #endregion
+
+ #region 私有字段
+
+ private readonly Dictionary _interceptRules;
+ private readonly Dictionary _interceptedWindows;
+ private readonly Timer _scanTimer;
+ private readonly Dispatcher _dispatcher;
+ private bool _isRunning;
+ private bool _disposed;
+
+ #endregion
+
+ #region 事件
+
+ public event EventHandler WindowIntercepted;
+ public event EventHandler WindowRestored;
+
+ #endregion
+
+ #region 构造函数
+
+ public FloatingWindowInterceptor()
+ {
+ _interceptRules = new Dictionary();
+ _interceptedWindows = new Dictionary();
+ _dispatcher = Dispatcher.CurrentDispatcher;
+
+ InitializeRules();
+ _scanTimer = new Timer(ScanForWindows, null, Timeout.Infinite, Timeout.Infinite);
+ }
+
+ #endregion
+
+ #region 初始化
+
+ private void InitializeRules()
+ {
+ // 希沃白板3 桌面悬浮窗
+ _interceptRules[InterceptType.SeewoWhiteboard3Floating] = new InterceptRule
+ {
+ Type = InterceptType.SeewoWhiteboard3Floating,
+ ProcessName = "EasiNote3",
+ WindowTitlePattern = "",
+ ClassNamePattern = "",
+ IsEnabled = true,
+ RequiresAdmin = false,
+ Description = "希沃白板3 桌面悬浮窗"
+ };
+
+ // 希沃白板5 桌面悬浮窗
+ _interceptRules[InterceptType.SeewoWhiteboard5Floating] = new InterceptRule
+ {
+ Type = InterceptType.SeewoWhiteboard5Floating,
+ ProcessName = "EasiNote5",
+ WindowTitlePattern = "",
+ ClassNamePattern = "",
+ IsEnabled = true,
+ RequiresAdmin = false,
+ Description = "希沃白板5 桌面悬浮窗"
+ };
+
+ // 希沃白板5C 桌面悬浮窗
+ _interceptRules[InterceptType.SeewoWhiteboard5CFloating] = new InterceptRule
+ {
+ Type = InterceptType.SeewoWhiteboard5CFloating,
+ ProcessName = "EasiNote5C",
+ WindowTitlePattern = "希沃白板",
+ ClassNamePattern = "EasiNote5C",
+ IsEnabled = true,
+ RequiresAdmin = false,
+ Description = "希沃白板5C 桌面悬浮窗"
+ };
+
+ // 希沃品课教师端 桌面悬浮窗
+ _interceptRules[InterceptType.SeewoPincoSideBarFloating] = new InterceptRule
+ {
+ Type = InterceptType.SeewoPincoSideBarFloating,
+ ProcessName = "SeewoPinco",
+ WindowTitlePattern = "品课",
+ ClassNamePattern = "SeewoPinco",
+ IsEnabled = true,
+ RequiresAdmin = false,
+ Description = "希沃品课教师端 桌面悬浮窗"
+ };
+
+ // 希沃品课教师端 画笔悬浮窗
+ _interceptRules[InterceptType.SeewoPincoDrawingFloating] = new InterceptRule
+ {
+ Type = InterceptType.SeewoPincoDrawingFloating,
+ ProcessName = "SeewoPinco",
+ WindowTitlePattern = "画笔",
+ ClassNamePattern = "SeewoPinco",
+ IsEnabled = true,
+ RequiresAdmin = false,
+ Description = "希沃品课教师端 画笔悬浮窗(包括PPT控件)"
+ };
+
+ // 希沃PPT小工具
+ _interceptRules[InterceptType.SeewoPPTFloating] = new InterceptRule
+ {
+ Type = InterceptType.SeewoPPTFloating,
+ ProcessName = "SeewoPPT",
+ WindowTitlePattern = "希沃PPT",
+ ClassNamePattern = "SeewoPPT",
+ IsEnabled = true,
+ RequiresAdmin = false,
+ Description = "希沃PPT小工具"
+ };
+
+ // AiClass 桌面悬浮窗
+ _interceptRules[InterceptType.AiClassFloating] = new InterceptRule
+ {
+ Type = InterceptType.AiClassFloating,
+ ProcessName = "AiClass",
+ WindowTitlePattern = "AiClass",
+ ClassNamePattern = "AiClass",
+ IsEnabled = true,
+ RequiresAdmin = false,
+ Description = "AiClass 桌面悬浮窗"
+ };
+
+ // 鸿合屏幕书写
+ _interceptRules[InterceptType.HiteAnnotationFloating] = new InterceptRule
+ {
+ Type = InterceptType.HiteAnnotationFloating,
+ ProcessName = "HiteAnnotation",
+ WindowTitlePattern = "鸿合",
+ ClassNamePattern = "HiteAnnotation",
+ IsEnabled = true,
+ RequiresAdmin = false,
+ Description = "鸿合屏幕书写"
+ };
+
+ // 畅言智慧课堂 桌面悬浮窗
+ _interceptRules[InterceptType.ChangYanFloating] = new InterceptRule
+ {
+ Type = InterceptType.ChangYanFloating,
+ ProcessName = "ChangYan",
+ WindowTitlePattern = "畅言",
+ ClassNamePattern = "ChangYan",
+ IsEnabled = true,
+ RequiresAdmin = true,
+ Description = "畅言智慧课堂 桌面悬浮窗"
+ };
+
+ // 畅言智慧课堂 PPT悬浮窗
+ _interceptRules[InterceptType.ChangYanPptFloating] = new InterceptRule
+ {
+ Type = InterceptType.ChangYanPptFloating,
+ ProcessName = "ChangYanPPT",
+ WindowTitlePattern = "畅言PPT",
+ ClassNamePattern = "ChangYanPPT",
+ IsEnabled = true,
+ RequiresAdmin = true,
+ Description = "畅言智慧课堂 PPT悬浮窗"
+ };
+
+ // 天喻教育云互动课堂 桌面悬浮窗
+ _interceptRules[InterceptType.IntelligentClassFloating] = new InterceptRule
+ {
+ Type = InterceptType.IntelligentClassFloating,
+ ProcessName = "IntelligentClass",
+ WindowTitlePattern = "天喻",
+ ClassNamePattern = "IntelligentClass",
+ IsEnabled = true,
+ RequiresAdmin = false,
+ Description = "天喻教育云互动课堂 桌面悬浮窗(包括PPT控件)"
+ };
+
+ // 希沃桌面 画笔悬浮窗
+ _interceptRules[InterceptType.SeewoDesktopAnnotationFloating] = new InterceptRule
+ {
+ Type = InterceptType.SeewoDesktopAnnotationFloating,
+ ProcessName = "SeewoDesktop",
+ WindowTitlePattern = "希沃桌面",
+ ClassNamePattern = "SeewoDesktop",
+ IsEnabled = true,
+ RequiresAdmin = false,
+ Description = "希沃桌面 画笔悬浮窗"
+ };
+
+ // 希沃桌面 侧栏悬浮窗
+ _interceptRules[InterceptType.SeewoDesktopSideBarFloating] = new InterceptRule
+ {
+ Type = InterceptType.SeewoDesktopSideBarFloating,
+ ProcessName = "SeewoDesktop",
+ WindowTitlePattern = "希沃桌面",
+ ClassNamePattern = "SeewoDesktop",
+ IsEnabled = true,
+ RequiresAdmin = true,
+ Description = "希沃桌面 侧栏悬浮窗"
+ };
+
+ // 测试规则 - 拦截所有小窗口
+ _interceptRules[InterceptType.SeewoWhiteboard3Floating] = new InterceptRule
+ {
+ Type = InterceptType.SeewoWhiteboard3Floating,
+ ProcessName = "", // 空字符串表示匹配所有进程
+ WindowTitlePattern = "",
+ ClassNamePattern = "",
+ IsEnabled = false, // 默认关闭,需要手动开启
+ RequiresAdmin = false,
+ Description = "测试规则 - 拦截所有小窗口"
+ };
+ }
+
+ #endregion
+
+ #region 公共方法
+
+ ///
+ /// 启动拦截器
+ ///
+ public void Start(int scanIntervalMs = 5000)
+ {
+ if (_isRunning) return;
+
+ _isRunning = true;
+ _scanTimer.Change(0, scanIntervalMs);
+ }
+
+ ///
+ /// 停止拦截器
+ ///
+ public void Stop()
+ {
+ if (!_isRunning) return;
+
+ _isRunning = false;
+ _scanTimer.Change(Timeout.Infinite, Timeout.Infinite);
+ }
+
+ ///
+ /// 设置拦截规则
+ ///
+ public void SetInterceptRule(InterceptType type, bool enabled)
+ {
+ if (_interceptRules.ContainsKey(type))
+ {
+ _interceptRules[type].IsEnabled = enabled;
+ }
+ }
+
+ ///
+ /// 获取拦截规则
+ ///
+ public InterceptRule GetInterceptRule(InterceptType type)
+ {
+ return _interceptRules.ContainsKey(type) ? _interceptRules[type] : null;
+ }
+
+ ///
+ /// 获取所有拦截规则
+ ///
+ public Dictionary GetAllRules()
+ {
+ return new Dictionary(_interceptRules);
+ }
+
+ ///
+ /// 手动扫描一次
+ ///
+ public void ScanOnce()
+ {
+ ScanForWindows(null);
+ }
+
+ ///
+ /// 恢复所有被拦截的窗口
+ ///
+ public void RestoreAllWindows()
+ {
+ var windowsToRestore = new List(_interceptedWindows.Keys);
+ foreach (var hWnd in windowsToRestore)
+ {
+ RestoreWindow(hWnd);
+ }
+ }
+
+ ///
+ /// 恢复指定窗口
+ ///
+ public bool RestoreWindow(IntPtr hWnd)
+ {
+ if (!_interceptedWindows.ContainsKey(hWnd)) return false;
+
+ if (IsWindow(hWnd))
+ {
+ ShowWindow(hWnd, SW_RESTORE);
+ _interceptedWindows.Remove(hWnd);
+
+ WindowRestored?.Invoke(this, new WindowRestoredEventArgs
+ {
+ WindowHandle = hWnd,
+ InterceptType = _interceptedWindows[hWnd]
+ });
+
+ return true;
+ }
+
+ _interceptedWindows.Remove(hWnd);
+ return false;
+ }
+
+ #endregion
+
+ #region 私有方法
+
+ private void ScanForWindows(object state)
+ {
+ if (!_isRunning) return;
+
+ try
+ {
+ EnumWindows(EnumWindowsCallback, IntPtr.Zero);
+ }
+ catch (Exception ex)
+ {
+ // 记录错误但不中断扫描
+ LogHelper.WriteLogToFile($"扫描窗口时发生错误: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ private bool EnumWindowsCallback(IntPtr hWnd, IntPtr lParam)
+ {
+ try
+ {
+ // 基本检查
+ if (!IsWindow(hWnd) || !IsWindowVisible(hWnd)) return true;
+
+ // 检查是否已经被拦截
+ if (_interceptedWindows.ContainsKey(hWnd)) return true;
+
+ // 获取窗口信息
+ var windowInfo = GetWindowInfo(hWnd);
+ if (windowInfo == null) return true;
+
+ // 输出调试信息到日志
+ LogHelper.WriteLogToFile($"检测到窗口: '{windowInfo.WindowTitle}' | 进程: '{windowInfo.ProcessName}' | 类名: '{windowInfo.ClassName}'", LogHelper.LogType.Event);
+
+ // 检查窗口样式,过滤掉系统窗口和主窗口
+ var exStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
+ var style = GetWindowLong(hWnd, -16); // GWL_STYLE
+
+ // 跳过工具窗口
+ if ((exStyle & WS_EX_TOOLWINDOW) != 0)
+ {
+ LogHelper.WriteLogToFile($"跳过工具窗口: {windowInfo.WindowTitle}", LogHelper.LogType.Event);
+ return true;
+ }
+
+ // 跳过主窗口(有标题栏和系统菜单的窗口)
+ const uint WS_CAPTION = 0x00C00000;
+ const uint WS_SYSMENU = 0x00080000;
+ if ((style & WS_CAPTION) != 0 && (style & WS_SYSMENU) != 0)
+ {
+ LogHelper.WriteLogToFile($"跳过主窗口: {windowInfo.WindowTitle}", LogHelper.LogType.Event);
+ return true;
+ }
+
+ // 检查窗口大小,跳过过大的窗口
+ var rect = new ForegroundWindowInfo.RECT();
+ GetWindowRect(hWnd, out rect);
+ var width = rect.Right - rect.Left;
+ var height = rect.Bottom - rect.Top;
+
+ if (width > 600 || height > 400)
+ {
+ LogHelper.WriteLogToFile($"跳过大窗口 ({width}x{height}): {windowInfo.WindowTitle}", LogHelper.LogType.Event);
+ return true;
+ }
+
+ // 检查是否匹配拦截规则
+ foreach (var rule in _interceptRules.Values)
+ {
+ if (!rule.IsEnabled) continue;
+
+ if (MatchesRule(windowInfo, rule))
+ {
+ LogHelper.WriteLogToFile($"匹配规则 '{rule.Description}',开始拦截窗口: {windowInfo.WindowTitle}", LogHelper.LogType.Event);
+ InterceptWindow(hWnd, rule);
+ break;
+ }
+ }
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"处理窗口时发生错误: {ex.Message}", LogHelper.LogType.Error);
+ return true;
+ }
+ }
+
+ private WindowInfo GetWindowInfo(IntPtr hWnd)
+ {
+ try
+ {
+ // 获取进程ID
+ GetWindowThreadProcessId(hWnd, out uint processId);
+ if (processId == 0) return null;
+
+ // 获取进程信息
+ var process = Process.GetProcessById((int)processId);
+ if (process == null) return null;
+
+ // 获取窗口标题
+ var titleBuilder = new StringBuilder(256);
+ GetWindowText(hWnd, titleBuilder, titleBuilder.Capacity);
+
+ // 获取窗口类名
+ var classBuilder = new StringBuilder(256);
+ GetClassName(hWnd, classBuilder, classBuilder.Capacity);
+
+ return new WindowInfo
+ {
+ Handle = hWnd,
+ ProcessId = processId,
+ ProcessName = process.ProcessName,
+ WindowTitle = titleBuilder.ToString(),
+ ClassName = classBuilder.ToString(),
+ Process = process
+ };
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ private bool MatchesRule(WindowInfo windowInfo, InterceptRule rule)
+ {
+ try
+ {
+ // 检查进程名(如果指定了进程名)
+ if (!string.IsNullOrEmpty(rule.ProcessName))
+ {
+ if (!windowInfo.ProcessName.ToLower().Contains(rule.ProcessName.ToLower()))
+ {
+ return false;
+ }
+ }
+
+ // 检查窗口标题(如果指定了模式)
+ if (!string.IsNullOrEmpty(rule.WindowTitlePattern))
+ {
+ if (!windowInfo.WindowTitle.ToLower().Contains(rule.WindowTitlePattern.ToLower()))
+ {
+ return false;
+ }
+ }
+
+ // 检查类名(如果指定了模式)
+ if (!string.IsNullOrEmpty(rule.ClassNamePattern))
+ {
+ if (!windowInfo.ClassName.ToLower().Contains(rule.ClassNamePattern.ToLower()))
+ {
+ return false;
+ }
+ }
+
+ // 如果所有检查都通过,就认为是目标窗口
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"匹配规则时发生错误: {ex.Message}", LogHelper.LogType.Error);
+ return false;
+ }
+ }
+
+ private void InterceptWindow(IntPtr hWnd, InterceptRule rule)
+ {
+ try
+ {
+ // 使用多种方法隐藏窗口
+ // 方法1:移动到屏幕外
+ SetWindowPos(hWnd, IntPtr.Zero, -2000, -2000, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW);
+
+ // 方法2:最小化窗口
+ ShowWindow(hWnd, SW_MINIMIZE);
+
+ // 方法3:隐藏窗口
+ ShowWindow(hWnd, SW_HIDE);
+
+ // 记录拦截的窗口
+ _interceptedWindows[hWnd] = rule.Type;
+
+ LogHelper.WriteLogToFile($"成功拦截窗口: {GetWindowTitle(hWnd)}", LogHelper.LogType.Event);
+
+ // 触发事件
+ WindowIntercepted?.Invoke(this, new WindowInterceptedEventArgs
+ {
+ WindowHandle = hWnd,
+ InterceptType = rule.Type,
+ Rule = rule,
+ WindowTitle = GetWindowTitle(hWnd)
+ });
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"拦截窗口时发生错误: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ private string GetWindowTitle(IntPtr hWnd)
+ {
+ try
+ {
+ var titleBuilder = new StringBuilder(256);
+ GetWindowText(hWnd, titleBuilder, titleBuilder.Capacity);
+ return titleBuilder.ToString();
+ }
+ catch
+ {
+ return "Unknown";
+ }
+ }
+
+ private bool IsMainWindow(IntPtr hWnd)
+ {
+ try
+ {
+ // 检查是否有父窗口
+ var parent = GetWindow(hWnd, 4); // GW_OWNER
+ if (parent != IntPtr.Zero) return false;
+
+ // 检查窗口样式
+ var style = GetWindowLong(hWnd, -16); // GWL_STYLE
+ var exStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
+
+ // 主窗口通常有 WS_CAPTION 和 WS_SYSMENU
+ const uint WS_CAPTION = 0x00C00000;
+ const uint WS_SYSMENU = 0x00080000;
+ const uint WS_MINIMIZEBOX = 0x00020000;
+ const uint WS_MAXIMIZEBOX = 0x00010000;
+
+ if ((style & WS_CAPTION) != 0 && (style & WS_SYSMENU) != 0)
+ {
+ return true; // 这可能是主窗口
+ }
+
+ // 检查窗口大小,主窗口通常比较大
+ var rect = new ForegroundWindowInfo.RECT();
+ GetWindowRect(hWnd, out rect);
+ var width = rect.Right - rect.Left;
+ var height = rect.Bottom - rect.Top;
+
+ // 如果窗口很大,可能是主窗口
+ if (width > 800 && height > 600)
+ {
+ return true;
+ }
+
+ return false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ #endregion
+
+ #region 辅助类
+
+ private class WindowInfo
+ {
+ public IntPtr Handle { get; set; }
+ public uint ProcessId { get; set; }
+ public string ProcessName { get; set; }
+ public string WindowTitle { get; set; }
+ public string ClassName { get; set; }
+ public Process Process { get; set; }
+ }
+
+ #endregion
+
+ #region 事件参数类
+
+ public class WindowInterceptedEventArgs : EventArgs
+ {
+ public IntPtr WindowHandle { get; set; }
+ public InterceptType InterceptType { get; set; }
+ public InterceptRule Rule { get; set; }
+ public string WindowTitle { get; set; }
+ }
+
+ public class WindowRestoredEventArgs : EventArgs
+ {
+ public IntPtr WindowHandle { get; set; }
+ public InterceptType InterceptType { get; set; }
+ }
+
+ #endregion
+
+ #region IDisposable
+
+ public void Dispose()
+ {
+ if (_disposed) return;
+
+ Stop();
+ _scanTimer?.Dispose();
+
+ // 恢复所有被拦截的窗口
+ RestoreAllWindows();
+
+ _disposed = true;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml
index d73b4879..a0b6dedf 100644
--- a/Ink Canvas/MainWindow.xaml
+++ b/Ink Canvas/MainWindow.xaml
@@ -2745,6 +2745,255 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs
index dd03c64f..8489e5ca 100644
--- a/Ink Canvas/MainWindow.xaml.cs
+++ b/Ink Canvas/MainWindow.xaml.cs
@@ -50,6 +50,9 @@ namespace Ink_Canvas
// 墨迹渐隐管理器
private InkFadeManager _inkFadeManager;
+ // 悬浮窗拦截管理器
+ private FloatingWindowInterceptorManager _floatingWindowInterceptorManager;
+
// 设置面板相关状态
private bool userChangedNoFocusModeInSettings;
@@ -534,6 +537,9 @@ namespace Ink_Canvas
// 初始化剪贴板监控
InitializeClipboardMonitoring();
+ // 初始化悬浮窗拦截管理器
+ InitializeFloatingWindowInterceptor();
+
// 初始化全局快捷键管理器
InitializeGlobalHotkeyManager();
diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingWindowInterceptor.cs b/Ink Canvas/MainWindow_cs/MW_FloatingWindowInterceptor.cs
new file mode 100644
index 00000000..93b9b550
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_FloatingWindowInterceptor.cs
@@ -0,0 +1,463 @@
+using Ink_Canvas.Helpers;
+using iNKORE.UI.WPF.Modern.Controls;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Ink_Canvas
+{
+ public partial class MainWindow : Window
+ {
+ #region 悬浮窗拦截功能
+
+ ///
+ /// 初始化悬浮窗拦截管理器
+ ///
+ private void InitializeFloatingWindowInterceptor()
+ {
+ try
+ {
+ _floatingWindowInterceptorManager = new FloatingWindowInterceptorManager();
+
+ // 订阅事件
+ _floatingWindowInterceptorManager.WindowIntercepted += OnFloatingWindowIntercepted;
+ _floatingWindowInterceptorManager.WindowRestored += OnFloatingWindowRestored;
+
+ // 初始化拦截器
+ _floatingWindowInterceptorManager.Initialize(Settings.Automation.FloatingWindowInterceptor);
+
+ // 加载UI状态
+ LoadFloatingWindowInterceptorUI();
+
+ LogHelper.WriteLogToFile("悬浮窗拦截管理器初始化完成", LogHelper.LogType.Event);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"初始化悬浮窗拦截管理器失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 加载悬浮窗拦截UI状态
+ ///
+ private void LoadFloatingWindowInterceptorUI()
+ {
+ try
+ {
+ if (!isLoaded) return;
+
+ // 设置主开关状态
+ ToggleSwitchFloatingWindowInterceptorEnabled.IsOn = Settings.Automation.FloatingWindowInterceptor.IsEnabled;
+
+ // 设置各个拦截规则的状态
+ foreach (var kvp in Settings.Automation.FloatingWindowInterceptor.InterceptRules)
+ {
+ var toggleName = $"ToggleSwitch{kvp.Key}";
+ var toggle = FindName(toggleName) as ToggleSwitch;
+ if (toggle != null)
+ {
+ toggle.IsOn = kvp.Value;
+ }
+ }
+
+ // 更新UI可见性
+ UpdateFloatingWindowInterceptorUI();
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"加载悬浮窗拦截UI状态失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 更新悬浮窗拦截UI
+ ///
+ private void UpdateFloatingWindowInterceptorUI()
+ {
+ try
+ {
+ var isEnabled = Settings.Automation.FloatingWindowInterceptor.IsEnabled;
+ FloatingWindowInterceptorGrid.Visibility = isEnabled ? Visibility.Visible : Visibility.Collapsed;
+
+ // 更新状态文本
+ if (_floatingWindowInterceptorManager != null)
+ {
+ var stats = _floatingWindowInterceptorManager.GetStatistics();
+ TextBlockFloatingWindowInterceptorStatus.Text = stats.IsRunning
+ ? $"拦截器运行中 - 已启用 {stats.EnabledRules}/{stats.TotalRules} 个规则"
+ : "拦截器未启动";
+ }
+ else
+ {
+ TextBlockFloatingWindowInterceptorStatus.Text = "拦截器未初始化";
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"更新悬浮窗拦截UI失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 窗口被拦截事件处理
+ ///
+ private void OnFloatingWindowIntercepted(object sender, FloatingWindowInterceptor.WindowInterceptedEventArgs e)
+ {
+ try
+ {
+ // 在UI线程中更新状态
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ UpdateFloatingWindowInterceptorUI();
+ }));
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"处理窗口拦截事件失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 窗口被恢复事件处理
+ ///
+ private void OnFloatingWindowRestored(object sender, FloatingWindowInterceptor.WindowRestoredEventArgs e)
+ {
+ try
+ {
+ // 在UI线程中更新状态
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ UpdateFloatingWindowInterceptorUI();
+ }));
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"处理窗口恢复事件失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ #endregion
+
+ #region 悬浮窗拦截事件处理
+
+ ///
+ /// 主开关切换事件
+ ///
+ private void ToggleSwitchFloatingWindowInterceptorEnabled_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+
+ try
+ {
+ Settings.Automation.FloatingWindowInterceptor.IsEnabled = ToggleSwitchFloatingWindowInterceptorEnabled.IsOn;
+
+ if (_floatingWindowInterceptorManager != null)
+ {
+ if (Settings.Automation.FloatingWindowInterceptor.IsEnabled)
+ {
+ _floatingWindowInterceptorManager.Start();
+ }
+ else
+ {
+ _floatingWindowInterceptorManager.Stop();
+ }
+ }
+
+ UpdateFloatingWindowInterceptorUI();
+ SaveSettingsToFile();
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"切换悬浮窗拦截主开关失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 希沃白板3拦截开关
+ ///
+ private void ToggleSwitchSeewoWhiteboard3Floating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.SeewoWhiteboard3Floating, ToggleSwitchSeewoWhiteboard3Floating.IsOn);
+ }
+
+ ///
+ /// 希沃白板5拦截开关
+ ///
+ private void ToggleSwitchSeewoWhiteboard5Floating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.SeewoWhiteboard5Floating, ToggleSwitchSeewoWhiteboard5Floating.IsOn);
+ }
+
+ ///
+ /// 希沃白板5C拦截开关
+ ///
+ private void ToggleSwitchSeewoWhiteboard5CFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.SeewoWhiteboard5CFloating, ToggleSwitchSeewoWhiteboard5CFloating.IsOn);
+ }
+
+ ///
+ /// 希沃品课侧栏拦截开关
+ ///
+ private void ToggleSwitchSeewoPincoSideBarFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.SeewoPincoSideBarFloating, ToggleSwitchSeewoPincoSideBarFloating.IsOn);
+ }
+
+ ///
+ /// 希沃品课画笔拦截开关
+ ///
+ private void ToggleSwitchSeewoPincoDrawingFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.SeewoPincoDrawingFloating, ToggleSwitchSeewoPincoDrawingFloating.IsOn);
+ }
+
+ ///
+ /// 希沃PPT小工具拦截开关
+ ///
+ private void ToggleSwitchSeewoPPTFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.SeewoPPTFloating, ToggleSwitchSeewoPPTFloating.IsOn);
+ }
+
+ ///
+ /// AiClass拦截开关
+ ///
+ private void ToggleSwitchAiClassFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.AiClassFloating, ToggleSwitchAiClassFloating.IsOn);
+ }
+
+ ///
+ /// 鸿合屏幕书写拦截开关
+ ///
+ private void ToggleSwitchHiteAnnotationFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.HiteAnnotationFloating, ToggleSwitchHiteAnnotationFloating.IsOn);
+ }
+
+ ///
+ /// 畅言智慧课堂拦截开关
+ ///
+ private void ToggleSwitchChangYanFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.ChangYanFloating, ToggleSwitchChangYanFloating.IsOn);
+ }
+
+ ///
+ /// 畅言PPT拦截开关
+ ///
+ private void ToggleSwitchChangYanPptFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.ChangYanPptFloating, ToggleSwitchChangYanPptFloating.IsOn);
+ }
+
+ ///
+ /// 天喻教育云拦截开关
+ ///
+ private void ToggleSwitchIntelligentClassFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.IntelligentClassFloating, ToggleSwitchIntelligentClassFloating.IsOn);
+ }
+
+ ///
+ /// 希沃桌面画笔拦截开关
+ ///
+ private void ToggleSwitchSeewoDesktopAnnotationFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.SeewoDesktopAnnotationFloating, ToggleSwitchSeewoDesktopAnnotationFloating.IsOn);
+ }
+
+ ///
+ /// 希沃桌面侧栏拦截开关
+ ///
+ private void ToggleSwitchSeewoDesktopSideBarFloating_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ SetInterceptRule(FloatingWindowInterceptor.InterceptType.SeewoDesktopSideBarFloating, ToggleSwitchSeewoDesktopSideBarFloating.IsOn);
+ }
+
+ ///
+ /// 设置拦截规则
+ ///
+ private void SetInterceptRule(FloatingWindowInterceptor.InterceptType type, bool enabled)
+ {
+ try
+ {
+ if (_floatingWindowInterceptorManager != null)
+ {
+ _floatingWindowInterceptorManager.SetInterceptRule(type, enabled);
+ }
+
+ // 更新设置
+ var ruleName = type.ToString();
+ if (Settings.Automation.FloatingWindowInterceptor.InterceptRules.ContainsKey(ruleName))
+ {
+ Settings.Automation.FloatingWindowInterceptor.InterceptRules[ruleName] = enabled;
+ }
+
+ SaveSettingsToFile();
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"设置拦截规则失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 启动拦截按钮点击
+ ///
+ private void BtnFloatingWindowInterceptorStart_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (_floatingWindowInterceptorManager != null)
+ {
+ _floatingWindowInterceptorManager.Start();
+ UpdateFloatingWindowInterceptorUI();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"启动悬浮窗拦截失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 停止拦截按钮点击
+ ///
+ private void BtnFloatingWindowInterceptorStop_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (_floatingWindowInterceptorManager != null)
+ {
+ _floatingWindowInterceptorManager.Stop();
+ UpdateFloatingWindowInterceptorUI();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"停止悬浮窗拦截失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 手动扫描按钮点击
+ ///
+ private void BtnFloatingWindowInterceptorScan_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (_floatingWindowInterceptorManager != null)
+ {
+ _floatingWindowInterceptorManager.ScanOnce();
+ UpdateFloatingWindowInterceptorUI();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"手动扫描失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 恢复所有窗口按钮点击
+ ///
+ private void BtnFloatingWindowInterceptorRestore_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (_floatingWindowInterceptorManager != null)
+ {
+ _floatingWindowInterceptorManager.RestoreAllWindows();
+ UpdateFloatingWindowInterceptorUI();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"恢复所有窗口失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 调试列出窗口按钮点击
+ ///
+ private void BtnFloatingWindowInterceptorDebug_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (_floatingWindowInterceptorManager != null)
+ {
+ // 更新状态显示
+ TextBlockFloatingWindowInterceptorStatus.Text = "正在调试扫描窗口...";
+
+ _floatingWindowInterceptorManager.DebugListAllWindows();
+
+ // 更新状态显示
+ TextBlockFloatingWindowInterceptorStatus.Text = "调试扫描完成,请查看日志文件";
+
+ LogHelper.WriteLogToFile("用户点击了调试列出窗口按钮", LogHelper.LogType.Event);
+ }
+ else
+ {
+ LogHelper.WriteLogToFile("拦截器管理器未初始化", LogHelper.LogType.Warning);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"调试列出窗口失败: {ex.Message}", LogHelper.LogType.Error);
+ TextBlockFloatingWindowInterceptorStatus.Text = "调试扫描失败";
+ }
+ }
+
+ ///
+ /// 测试拦截按钮点击
+ ///
+ private void BtnFloatingWindowInterceptorTest_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (_floatingWindowInterceptorManager != null)
+ {
+ // 更新状态显示
+ TextBlockFloatingWindowInterceptorStatus.Text = "正在测试拦截功能...";
+
+ // 启用测试规则
+ _floatingWindowInterceptorManager.SetInterceptRule(FloatingWindowInterceptor.InterceptType.SeewoWhiteboard3Floating, true);
+
+ // 执行一次扫描
+ _floatingWindowInterceptorManager.ScanOnce();
+
+ // 更新状态显示
+ TextBlockFloatingWindowInterceptorStatus.Text = "测试拦截完成,请查看日志文件";
+
+ LogHelper.WriteLogToFile("用户点击了测试拦截按钮", LogHelper.LogType.Event);
+ }
+ else
+ {
+ LogHelper.WriteLogToFile("拦截器管理器未初始化", LogHelper.LogType.Warning);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"测试拦截失败: {ex.Message}", LogHelper.LogType.Error);
+ TextBlockFloatingWindowInterceptorStatus.Text = "测试拦截失败";
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Resources/Settings.cs b/Ink Canvas/Resources/Settings.cs
index a743cb18..e59d3037 100644
--- a/Ink Canvas/Resources/Settings.cs
+++ b/Ink Canvas/Resources/Settings.cs
@@ -456,6 +456,42 @@ namespace Ink_Canvas
[JsonProperty("isAutoEnterAnnotationAfterKillHite")]
public bool IsAutoEnterAnnotationAfterKillHite { get; set; }
+
+ [JsonProperty("floatingWindowInterceptor")]
+ public FloatingWindowInterceptorSettings FloatingWindowInterceptor { get; set; } = new FloatingWindowInterceptorSettings();
+ }
+
+ public class FloatingWindowInterceptorSettings
+ {
+ [JsonProperty("isEnabled")]
+ public bool IsEnabled { get; set; } = false;
+
+ [JsonProperty("scanIntervalMs")]
+ public int ScanIntervalMs { get; set; } = 5000;
+
+ [JsonProperty("interceptRules")]
+ public Dictionary InterceptRules { get; set; } = new Dictionary
+ {
+ { "SeewoWhiteboard3Floating", true },
+ { "SeewoWhiteboard5Floating", true },
+ { "SeewoWhiteboard5CFloating", true },
+ { "SeewoPincoSideBarFloating", true },
+ { "SeewoPincoDrawingFloating", true },
+ { "SeewoPPTFloating", true },
+ { "AiClassFloating", true },
+ { "HiteAnnotationFloating", true },
+ { "ChangYanFloating", true },
+ { "ChangYanPptFloating", true },
+ { "IntelligentClassFloating", true },
+ { "SeewoDesktopAnnotationFloating", true },
+ { "SeewoDesktopSideBarFloating", true }
+ };
+
+ [JsonProperty("autoStart")]
+ public bool AutoStart { get; set; } = false;
+
+ [JsonProperty("showNotifications")]
+ public bool ShowNotifications { get; set; } = true;
}
public class Advanced