From 61dbcf762ce796dac5597c77bccd91a54ee74ec6 Mon Sep 17 00:00:00 2001
From: CJKmkp <2564608840@qq.com>
Date: Sun, 26 Oct 2025 00:21:10 +0800
Subject: [PATCH] =?UTF-8?q?add:=E7=82=B9=E5=90=8D=E5=BF=AB=E6=8A=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Ink Canvas/Converters/PositionConverters.cs | 35 +++
Ink Canvas/MainWindow.xaml | 11 +-
Ink Canvas/MainWindow.xaml.cs | 62 +++-
Ink Canvas/MainWindow_cs/MW_Settings.cs | 14 +
Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs | 2 +
Ink Canvas/Resources/Settings.cs | 2 +
Ink Canvas/Windows/QuickDrawFloatingButton.cs | 125 ++++++++
.../Windows/QuickDrawFloatingButton.xaml | 43 +++
Ink Canvas/Windows/QuickDrawWindow.cs | 283 ++++++++++++++++++
Ink Canvas/Windows/QuickDrawWindow.xaml | 77 +++++
10 files changed, 652 insertions(+), 2 deletions(-)
create mode 100644 Ink Canvas/Converters/PositionConverters.cs
create mode 100644 Ink Canvas/Windows/QuickDrawFloatingButton.cs
create mode 100644 Ink Canvas/Windows/QuickDrawFloatingButton.xaml
create mode 100644 Ink Canvas/Windows/QuickDrawWindow.cs
create mode 100644 Ink Canvas/Windows/QuickDrawWindow.xaml
diff --git a/Ink Canvas/Converters/PositionConverters.cs b/Ink Canvas/Converters/PositionConverters.cs
new file mode 100644
index 00000000..d97093e4
--- /dev/null
+++ b/Ink Canvas/Converters/PositionConverters.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace Ink_Canvas.Converters
+{
+ ///
+ /// 位置计算转换器
+ ///
+ public class PositionConverters
+ {
+ ///
+ /// 减法转换器
+ ///
+ public class SubtractConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is double baseValue && parameter is string paramStr)
+ {
+ if (double.TryParse(paramStr, out double subtractValue))
+ {
+ return baseValue - subtractValue;
+ }
+ }
+ return value;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml
index 7238863e..c9d0d120 100644
--- a/Ink Canvas/MainWindow.xaml
+++ b/Ink Canvas/MainWindow.xaml
@@ -3249,6 +3249,15 @@
FontWeight="Bold"
Toggled="ToggleSwitchShowRandomAndSingleDraw_Toggled" />
+
+
+
+
@@ -3311,7 +3320,7 @@
VerticalAlignment="Center" FontSize="14" Margin="0,0,16,0" />
diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs
index a14d50ff..d0f2ceaf 100644
--- a/Ink Canvas/MainWindow.xaml.cs
+++ b/Ink Canvas/MainWindow.xaml.cs
@@ -60,6 +60,9 @@ namespace Ink_Canvas
// 悬浮窗拦截管理器
private FloatingWindowInterceptorManager _floatingWindowInterceptorManager;
+ // 快抽悬浮按钮
+ private QuickDrawFloatingButton _quickDrawFloatingButton;
+
// 设置面板相关状态
private bool userChangedNoFocusModeInSettings;
private bool isTemporarilyDisablingNoFocusMode = false;
@@ -530,6 +533,9 @@ namespace Ink_Canvas
else
RadioCrashNoAction.IsChecked = true;
+ // 显示快抽悬浮按钮
+ ShowQuickDrawFloatingButton();
+
// 如果当前不是黑板模式,则切换到黑板模式
if (currentMode == 0)
{
@@ -668,6 +674,19 @@ namespace Ink_Canvas
private void Window_Closing(object sender, CancelEventArgs e)
{
LogHelper.WriteLogToFile("Ink Canvas closing", LogHelper.LogType.Event);
+ try
+ {
+ if (_quickDrawFloatingButton != null)
+ {
+ _quickDrawFloatingButton.Close();
+ _quickDrawFloatingButton = null;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"关闭快抽悬浮按钮时出错: {ex.Message}", LogHelper.LogType.Error);
+ }
+
if (!CloseIsFromButton && Settings.Advanced.IsSecondConfirmWhenShutdownApp)
{
// 第一个确认对话框
@@ -2509,7 +2528,9 @@ namespace Ink_Canvas
BoardHighlighterWidthSlider,
InkWidthSlider,
InkAlphaSlider,
- HighlighterWidthSlider
+ HighlighterWidthSlider,
+ MLAvoidanceHistorySlider,
+ MLAvoidanceWeightSlider
};
foreach (var slider in sliders)
@@ -3053,6 +3074,45 @@ namespace Ink_Canvas
}
}
+ ///
+ /// 显示快抽悬浮按钮
+ ///
+ private void ShowQuickDrawFloatingButton()
+ {
+ try
+ {
+ // 检查设置是否启用快抽功能
+ if (Settings?.RandSettings?.EnableQuickDraw != true)
+ {
+ // 如果设置未启用,确保悬浮按钮被关闭
+ if (_quickDrawFloatingButton != null)
+ {
+ _quickDrawFloatingButton.Close();
+ _quickDrawFloatingButton = null;
+ }
+ return;
+ }
+
+ // 如果已经存在悬浮按钮,先关闭它
+ if (_quickDrawFloatingButton != null)
+ {
+ _quickDrawFloatingButton.Close();
+ _quickDrawFloatingButton = null;
+ }
+
+ // 创建并显示悬浮按钮
+ _quickDrawFloatingButton = new QuickDrawFloatingButton();
+ _quickDrawFloatingButton.Show();
+
+ LogHelper.WriteLogToFile("快抽悬浮按钮已显示", LogHelper.LogType.Trace);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"显示快抽悬浮按钮失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+
#endregion
}
}
diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs
index c494bda9..4624ac44 100644
--- a/Ink Canvas/MainWindow_cs/MW_Settings.cs
+++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs
@@ -2769,6 +2769,20 @@ namespace Ink_Canvas
SaveSettingsToFile();
}
+ private void ToggleSwitchEnableQuickDraw_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+
+ // 获取开关状态并保存到设置中
+ Settings.RandSettings.EnableQuickDraw = ToggleSwitchEnableQuickDraw.IsOn;
+
+ // 保存设置到文件
+ SaveSettingsToFile();
+
+ // 根据设置状态显示或隐藏快抽悬浮按钮
+ ShowQuickDrawFloatingButton();
+ }
+
private void ToggleSwitchExternalCaller_Toggled(object sender, RoutedEventArgs e)
{
if (!isLoaded) return;
diff --git a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs
index 93d50998..85e8ec86 100644
--- a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs
+++ b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs
@@ -876,6 +876,7 @@ namespace Ink_Canvas
RandWindowOnceCloseLatencySlider.Value = Settings.RandSettings.RandWindowOnceCloseLatency;
RandWindowOnceMaxStudentsSlider.Value = Settings.RandSettings.RandWindowOnceMaxStudents;
ToggleSwitchShowRandomAndSingleDraw.IsOn = Settings.RandSettings.ShowRandomAndSingleDraw;
+ ToggleSwitchEnableQuickDraw.IsOn = Settings.RandSettings.EnableQuickDraw;
ToggleSwitchExternalCaller.IsOn = Settings.RandSettings.DirectCallCiRand;
ComboBoxExternalCallerType.SelectedIndex = Settings.RandSettings.ExternalCallerType;
RandomDrawPanel.Visibility = Settings.RandSettings.ShowRandomAndSingleDraw ? Visibility.Visible : Visibility.Collapsed;
@@ -921,6 +922,7 @@ namespace Ink_Canvas
ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn = Settings.RandSettings.DisplayRandWindowNamesInputBtn;
RandWindowOnceCloseLatencySlider.Value = Settings.RandSettings.RandWindowOnceCloseLatency;
RandWindowOnceMaxStudentsSlider.Value = Settings.RandSettings.RandWindowOnceMaxStudents;
+ ToggleSwitchEnableQuickDraw.IsOn = Settings.RandSettings.EnableQuickDraw;
ToggleSwitchExternalCaller.IsOn = Settings.RandSettings.DirectCallCiRand;
ComboBoxExternalCallerType.SelectedIndex = Settings.RandSettings.ExternalCallerType;
ToggleSwitchUseLegacyTimerUI.IsOn = Settings.RandSettings.UseLegacyTimerUI;
diff --git a/Ink Canvas/Resources/Settings.cs b/Ink Canvas/Resources/Settings.cs
index 9929a55d..395ea46d 100644
--- a/Ink Canvas/Resources/Settings.cs
+++ b/Ink Canvas/Resources/Settings.cs
@@ -658,6 +658,8 @@ namespace Ink_Canvas
public int MLAvoidanceHistoryCount { get; set; } = 20;
[JsonProperty("mlAvoidanceWeight")]
public double MLAvoidanceWeight { get; set; } = 0.8;
+ [JsonProperty("enableQuickDraw")]
+ public bool EnableQuickDraw { get; set; } = true;
}
public class CustomPickNameBackground
diff --git a/Ink Canvas/Windows/QuickDrawFloatingButton.cs b/Ink Canvas/Windows/QuickDrawFloatingButton.cs
new file mode 100644
index 00000000..50d96931
--- /dev/null
+++ b/Ink Canvas/Windows/QuickDrawFloatingButton.cs
@@ -0,0 +1,125 @@
+using Ink_Canvas.Helpers;
+using System;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Interop;
+using System.Windows.Media;
+using System.Runtime.InteropServices;
+using System.Windows.Threading;
+
+namespace Ink_Canvas
+{
+ ///
+ /// 快抽悬浮按钮
+ ///
+ public partial class QuickDrawFloatingButton : Window
+ {
+ public QuickDrawFloatingButton()
+ {
+ InitializeComponent();
+
+ // 设置无焦点状态
+ this.Focusable = false;
+ this.ShowInTaskbar = false;
+ }
+
+
+ private void FloatingButton_Loaded(object sender, RoutedEventArgs e)
+ {
+ // 设置位置到屏幕右下角稍微靠近中部
+ SetPositionToBottomRight();
+
+ // 应用置顶
+ ApplyFloatingButtonTopmost();
+ }
+
+ private void SetPositionToBottomRight()
+ {
+ try
+ {
+ // 获取主屏幕的工作区域
+ var workingArea = SystemParameters.WorkArea;
+ this.Left = workingArea.Right - this.Width - 0;
+ this.Top = workingArea.Bottom - this.Height - 200;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"设置悬浮按钮位置失败: {ex.Message}", LogHelper.LogType.Error);
+ // 如果计算失败,使用默认位置
+ this.Left = 720;
+ this.Top = 400;
+ }
+ }
+
+ private void FloatingButton_Click(object sender, MouseButtonEventArgs e)
+ {
+ try
+ {
+ // 打开快抽窗口
+ var quickDrawWindow = new QuickDrawWindow();
+ quickDrawWindow.ShowDialog();
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"打开快抽窗口失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+
+
+
+ #region Win32 API 声明和置顶管理
+ [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 int GetWindowLong(IntPtr hWnd, int nIndex);
+
+ [DllImport("user32.dll")]
+ private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
+
+ private const int GWL_EXSTYLE = -20;
+ private const int WS_EX_TOPMOST = 0x00000008;
+ private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
+ private const uint SWP_NOMOVE = 0x0002;
+ private const uint SWP_NOSIZE = 0x0001;
+ private const uint SWP_NOACTIVATE = 0x0010;
+ private const uint SWP_SHOWWINDOW = 0x0040;
+ private const uint SWP_NOOWNERZORDER = 0x0200;
+
+ ///
+ /// 应用悬浮按钮置顶
+ ///
+ private void ApplyFloatingButtonTopmost()
+ {
+ try
+ {
+ var hwnd = new WindowInteropHelper(this).Handle;
+ if (hwnd == IntPtr.Zero) return;
+
+ // 强制激活窗口
+ Activate();
+ Focus();
+
+ // 设置WPF的Topmost属性
+ Topmost = true;
+
+ // 使用Win32 API强制置顶
+ // 1. 设置窗口样式为置顶
+ int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+ SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST);
+
+ // 2. 使用SetWindowPos确保窗口在最顶层
+ SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
+
+ LogHelper.WriteLogToFile("快抽悬浮按钮已应用置顶", LogHelper.LogType.Trace);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"应用快抽悬浮按钮置顶失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+ #endregion
+ }
+}
diff --git a/Ink Canvas/Windows/QuickDrawFloatingButton.xaml b/Ink Canvas/Windows/QuickDrawFloatingButton.xaml
new file mode 100644
index 00000000..d743c383
--- /dev/null
+++ b/Ink Canvas/Windows/QuickDrawFloatingButton.xaml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ink Canvas/Windows/QuickDrawWindow.cs b/Ink Canvas/Windows/QuickDrawWindow.cs
new file mode 100644
index 00000000..eb92a816
--- /dev/null
+++ b/Ink Canvas/Windows/QuickDrawWindow.cs
@@ -0,0 +1,283 @@
+using Ink_Canvas.Helpers;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Interop;
+using System.Windows.Media;
+using System.Windows.Threading;
+using System.Runtime.InteropServices;
+using Newtonsoft.Json;
+using System.IO;
+
+namespace Ink_Canvas
+{
+ ///
+ /// 快抽窗口
+ ///
+ public partial class QuickDrawWindow : Window
+ {
+ private Random random = new Random();
+ private int autoCloseWaitTime = 2500; // 自动关闭等待时间(毫秒)
+ private List nameList = new List(); // 名单列表
+
+ public QuickDrawWindow()
+ {
+ InitializeComponent();
+ this.Focusable = false;
+ this.ShowInTaskbar = false;
+ InitializeSettings();
+ LoadNamesFromFile();
+ StartQuickDraw();
+ }
+
+ private void InitializeSettings()
+ {
+ try
+ {
+ if (MainWindow.Settings?.RandSettings != null)
+ {
+ autoCloseWaitTime = (int)MainWindow.Settings.RandSettings.RandWindowOnceCloseLatency * 1000;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"初始化快抽窗口设置失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ private void LoadNamesFromFile()
+ {
+ try
+ {
+ string namesFilePath = App.RootPath + "Names.txt";
+ if (File.Exists(namesFilePath))
+ {
+ string content = File.ReadAllText(namesFilePath);
+ nameList = content.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries)
+ .Select(name => name.Trim())
+ .Where(name => !string.IsNullOrEmpty(name))
+ .ToList();
+ }
+ else
+ {
+ nameList.Clear();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"加载名单文件失败: {ex.Message}", LogHelper.LogType.Error);
+ nameList.Clear();
+ }
+ }
+
+ private void StartQuickDraw()
+ {
+ try
+ {
+ // 延迟100ms后开始抽选动画
+ new System.Threading.Thread(() =>
+ {
+ System.Threading.Thread.Sleep(100);
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ StartQuickDrawAnimation();
+ });
+ }).Start();
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"开始快抽失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 快抽动画
+ ///
+ private void StartQuickDrawAnimation()
+ {
+ const int animationTimes = 100; // 动画次数
+ const int sleepTime = 5; // 每次动画间隔(毫秒)
+
+ new System.Threading.Thread(() =>
+ {
+ if (nameList.Count > 0)
+ {
+ // 有名单时,从名单中抽选
+ StartNameDrawAnimation(animationTimes, sleepTime);
+ }
+ else
+ {
+ // 没有名单时,从1-60数字中抽选
+ StartNumberDrawAnimation(animationTimes, sleepTime);
+ }
+ }).Start();
+ }
+
+ ///
+ /// 名单抽选动画
+ ///
+ private void StartNameDrawAnimation(int animationTimes, int sleepTime)
+ {
+ List usedNames = new List();
+
+ for (int i = 0; i < animationTimes; i++)
+ {
+ // 随机选择一个名字进行动画显示,避免立即重复
+ string randomName;
+ do
+ {
+ randomName = nameList[random.Next(0, nameList.Count)];
+ } while (usedNames.Count > 0 && usedNames[usedNames.Count - 1] == randomName);
+
+ usedNames.Add(randomName);
+
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ MainResultDisplay.Text = randomName;
+ });
+
+ System.Threading.Thread.Sleep(sleepTime);
+ }
+
+ // 动画结束,显示最终结果
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ // 随机选择一个最终名字
+ string finalName = nameList[random.Next(0, nameList.Count)];
+ MainResultDisplay.Text = finalName;
+ });
+
+ // 显示结果后,等待一段时间让用户看到结果,然后关闭窗口
+ new System.Threading.Thread(() =>
+ {
+ System.Threading.Thread.Sleep(autoCloseWaitTime);
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ Close();
+ });
+ }).Start();
+ }
+
+ ///
+ /// 数字抽选动画
+ ///
+ private void StartNumberDrawAnimation(int animationTimes, int sleepTime)
+ {
+ List usedNumbers = new List();
+
+ for (int i = 0; i < animationTimes; i++)
+ {
+ // 随机选择一个数字进行动画显示,避免立即重复
+ int randomNumber;
+ do
+ {
+ randomNumber = random.Next(1, 61); // 1-60
+ } while (usedNumbers.Count > 0 && usedNumbers[usedNumbers.Count - 1] == randomNumber);
+
+ usedNumbers.Add(randomNumber);
+
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ MainResultDisplay.Text = randomNumber.ToString();
+ });
+
+ System.Threading.Thread.Sleep(sleepTime);
+ }
+
+ // 动画结束,显示最终结果
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ // 随机选择一个最终数字
+ int finalNumber = random.Next(1, 61);
+ MainResultDisplay.Text = finalNumber.ToString();
+ });
+
+ // 显示结果后,等待一段时间让用户看到结果,然后关闭窗口
+ new System.Threading.Thread(() =>
+ {
+ System.Threading.Thread.Sleep(autoCloseWaitTime);
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ Close();
+ });
+ }).Start();
+ }
+
+
+ private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ // 窗口关闭时的清理工作
+ }
+
+ private void WindowDragMove(object sender, MouseButtonEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ DragMove();
+ }
+
+
+ #region Win32 API 声明和置顶管理
+ [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 int GetWindowLong(IntPtr hWnd, int nIndex);
+
+ [DllImport("user32.dll")]
+ private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
+
+ private const int GWL_EXSTYLE = -20;
+ private const int WS_EX_TOPMOST = 0x00000008;
+ private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
+ private const uint SWP_NOMOVE = 0x0002;
+ private const uint SWP_NOSIZE = 0x0001;
+ private const uint SWP_NOACTIVATE = 0x0010;
+ private const uint SWP_SHOWWINDOW = 0x0040;
+ private const uint SWP_NOOWNERZORDER = 0x0200;
+
+ ///
+ /// 应用快抽窗口置顶
+ ///
+ private void ApplyQuickDrawWindowTopmost()
+ {
+ try
+ {
+ var hwnd = new WindowInteropHelper(this).Handle;
+ if (hwnd == IntPtr.Zero) return;
+
+ // 设置WPF的Topmost属性
+ Topmost = true;
+
+ // 使用Win32 API强制置顶
+ // 1. 设置窗口样式为置顶
+ int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+ SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST);
+
+ // 2. 使用SetWindowPos确保窗口在最顶层
+ SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
+
+ LogHelper.WriteLogToFile("快抽窗口已应用置顶", LogHelper.LogType.Trace);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"应用快抽窗口置顶失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 窗口加载事件处理,确保置顶
+ ///
+ private void QuickDrawWindow_Loaded(object sender, RoutedEventArgs e)
+ {
+ // 使用延迟确保窗口完全加载后再应用置顶
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ ApplyQuickDrawWindowTopmost();
+ }), DispatcherPriority.Loaded);
+ }
+ #endregion
+ }
+}
diff --git a/Ink Canvas/Windows/QuickDrawWindow.xaml b/Ink Canvas/Windows/QuickDrawWindow.xaml
new file mode 100644
index 00000000..67891ed8
--- /dev/null
+++ b/Ink Canvas/Windows/QuickDrawWindow.xaml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+