From 501c034cfab1e7764ec69a58e3760852c75152a0 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 25 Oct 2025 21:14:59 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix:=E7=82=B9=E5=90=8DUI=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E4=B8=BB=E9=A2=98=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Resources/Styles/Dark.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Ink Canvas/Resources/Styles/Dark.xaml b/Ink Canvas/Resources/Styles/Dark.xaml index fb1ee834..b9761ed8 100644 --- a/Ink Canvas/Resources/Styles/Dark.xaml +++ b/Ink Canvas/Resources/Styles/Dark.xaml @@ -88,8 +88,8 @@ - - + + From 60b0149a9cec85a151a28c2af41e69752c7b7ace Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sun, 26 Oct 2025 00:00:13 +0800 Subject: [PATCH 2/4] =?UTF-8?q?add:=E6=96=B0=E7=82=B9=E5=90=8DUI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow.xaml | 56 + .../MainWindow_cs/MW_FloatingBarIcons.cs | 42 +- Ink Canvas/MainWindow_cs/MW_Settings.cs | 29 + Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs | 6 + .../Resources/NewRollCallWindowResources.xaml | 39 + Ink Canvas/Resources/Settings.cs | 8 + Ink Canvas/Windows/NamesInputWindow.xaml | 39 +- Ink Canvas/Windows/NamesInputWindow.xaml.cs | 110 ++ Ink Canvas/Windows/NewStyleRollCallWindow.cs | 1589 +++++++++++++++++ .../Windows/NewStyleRollCallWindow.xaml | 509 ++++++ 10 files changed, 2412 insertions(+), 15 deletions(-) create mode 100644 Ink Canvas/Resources/NewRollCallWindowResources.xaml create mode 100644 Ink Canvas/Windows/NewStyleRollCallWindow.cs create mode 100644 Ink Canvas/Windows/NewStyleRollCallWindow.xaml diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index 48a621a3..7238863e 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -3299,6 +3299,62 @@ FontFamily="Consolas" Text="{Binding ElementName=RandWindowOnceMaxStudentsSlider, Path=Value, Converter={StaticResource IntNumberToString}}" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // 使用延迟确保窗口完全显示后再强制置顶 + randWindow.Dispatcher.BeginInvoke(new Action(() => { try { @@ -1126,6 +1135,7 @@ namespace Ink_Canvas LogHelper.WriteLogToFile($"强制置顶RandWindow失败: {ex.Message}", LogHelper.LogType.Error); } }), DispatcherPriority.Loaded); + } } public void CheckEraserTypeTab() @@ -1232,14 +1242,30 @@ namespace Ink_Canvas { MessageBox.Show("无法调用外部点名:" + ex.Message); - // 调用失败时回退到默认的随机点名窗口 - new RandWindow(Settings, true).ShowDialog(); + // 调用失败时回退到相应的点名窗口 + if (Settings.RandSettings.UseNewRollCallUI) + { + new NewStyleRollCallWindow(Settings, true).ShowDialog(); // 单次抽模式 + } + else + { + new RandWindow(Settings, true).ShowDialog(); + } } } else { - // 使用默认的随机点名窗口 - new RandWindow(Settings, true).ShowDialog(); + // 根据设置决定使用哪个点名窗口 + if (Settings.RandSettings.UseNewRollCallUI) + { + // 使用新点名UI - 单次抽模式 + new NewStyleRollCallWindow(Settings, true).ShowDialog(); + } + else + { + // 使用默认的随机点名窗口 + new RandWindow(Settings, true).ShowDialog(); + } } } diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs index e5e06c8f..c494bda9 100644 --- a/Ink Canvas/MainWindow_cs/MW_Settings.cs +++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs @@ -2671,6 +2671,35 @@ namespace Ink_Canvas SaveSettingsToFile(); } + // 新点名UI设置事件处理 + private void ToggleSwitchUseNewRollCallUI_Toggled(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + Settings.RandSettings.UseNewRollCallUI = ToggleSwitchUseNewRollCallUI.IsOn; + SaveSettingsToFile(); + } + + private void ToggleSwitchEnableMLAvoidance_Toggled(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + Settings.RandSettings.EnableMLAvoidance = ToggleSwitchEnableMLAvoidance.IsOn; + SaveSettingsToFile(); + } + + private void MLAvoidanceHistorySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) + { + if (!isLoaded) return; + Settings.RandSettings.MLAvoidanceHistoryCount = (int)MLAvoidanceHistorySlider.Value; + SaveSettingsToFile(); + } + + private void MLAvoidanceWeightSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) + { + if (!isLoaded) return; + Settings.RandSettings.MLAvoidanceWeight = MLAvoidanceWeightSlider.Value; + SaveSettingsToFile(); + } + private void ProgressiveReminderVolumeSlider_ValueChanged(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 c9699bb8..93d50998 100644 --- a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs +++ b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs @@ -886,6 +886,12 @@ namespace Ink_Canvas ToggleSwitchUseNewStyleUI.IsOn = Settings.RandSettings.UseNewStyleUI; ToggleSwitchEnableOvertimeCountUp.IsOn = Settings.RandSettings.EnableOvertimeCountUp; + // 新点名UI设置 + ToggleSwitchUseNewRollCallUI.IsOn = Settings.RandSettings.UseNewRollCallUI; + ToggleSwitchEnableMLAvoidance.IsOn = Settings.RandSettings.EnableMLAvoidance; + MLAvoidanceHistorySlider.Value = Settings.RandSettings.MLAvoidanceHistoryCount; + MLAvoidanceWeightSlider.Value = Settings.RandSettings.MLAvoidanceWeight; + bool canEnableRedText = Settings.RandSettings.EnableOvertimeCountUp && Settings.RandSettings.EnableOvertimeRedText; ToggleSwitchEnableOvertimeRedText.IsOn = canEnableRedText; if (!canEnableRedText) diff --git a/Ink Canvas/Resources/NewRollCallWindowResources.xaml b/Ink Canvas/Resources/NewRollCallWindowResources.xaml new file mode 100644 index 00000000..0eceb7f8 --- /dev/null +++ b/Ink Canvas/Resources/NewRollCallWindowResources.xaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ink Canvas/Resources/Settings.cs b/Ink Canvas/Resources/Settings.cs index ba633b85..9929a55d 100644 --- a/Ink Canvas/Resources/Settings.cs +++ b/Ink Canvas/Resources/Settings.cs @@ -650,6 +650,14 @@ namespace Ink_Canvas public double ProgressiveReminderVolume { get; set; } = 1.0; [JsonProperty("progressiveReminderSoundPath")] public string ProgressiveReminderSoundPath { get; set; } = ""; + [JsonProperty("useNewRollCallUI")] + public bool UseNewRollCallUI { get; set; } = true; + [JsonProperty("enableMLAvoidance")] + public bool EnableMLAvoidance { get; set; } = true; + [JsonProperty("mlAvoidanceHistoryCount")] + public int MLAvoidanceHistoryCount { get; set; } = 20; + [JsonProperty("mlAvoidanceWeight")] + public double MLAvoidanceWeight { get; set; } = 0.8; } public class CustomPickNameBackground diff --git a/Ink Canvas/Windows/NamesInputWindow.xaml b/Ink Canvas/Windows/NamesInputWindow.xaml index f397f495..0c9add60 100644 --- a/Ink Canvas/Windows/NamesInputWindow.xaml +++ b/Ink Canvas/Windows/NamesInputWindow.xaml @@ -5,15 +5,40 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Ink_Canvas" mc:Ignorable="d" FontFamily="Microsoft YaHei UI" ui:WindowHelper.UseModernWindowStyle="True" - ui:ThemeManager.RequestedTheme="Light" WindowStartupLocation="CenterScreen" + WindowStartupLocation="CenterScreen" xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" Topmost="True" Title="Ink Canvas 抽奖 - 名单导入" Height="500" Width="400" Loaded="Window_Loaded" Closing="Window_Closing"> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 3/4] =?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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 991a8237007ec448688eea23fc013fd12f202f00 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sun, 26 Oct 2025 00:24:28 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AutomaticUpdateVersionControl.txt | 2 +- Ink Canvas/AssemblyInfo.cs | 4 ++-- Ink Canvas/Properties/AssemblyInfo.cs | 4 ++-- UpdateLog.md | 2 ++ 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/AutomaticUpdateVersionControl.txt b/AutomaticUpdateVersionControl.txt index 68fc7c72..80c8c54c 100644 --- a/AutomaticUpdateVersionControl.txt +++ b/AutomaticUpdateVersionControl.txt @@ -1 +1 @@ -1.7.15.0 +1.7.16.0 diff --git a/Ink Canvas/AssemblyInfo.cs b/Ink Canvas/AssemblyInfo.cs index cbf311f0..25087510 100644 --- a/Ink Canvas/AssemblyInfo.cs +++ b/Ink Canvas/AssemblyInfo.cs @@ -49,5 +49,5 @@ using System.Windows; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.7.15.0")] -[assembly: AssemblyFileVersion("1.7.15.0")] +[assembly: AssemblyVersion("1.7.16.0")] +[assembly: AssemblyFileVersion("1.7.16.0")] diff --git a/Ink Canvas/Properties/AssemblyInfo.cs b/Ink Canvas/Properties/AssemblyInfo.cs index cbf311f0..25087510 100644 --- a/Ink Canvas/Properties/AssemblyInfo.cs +++ b/Ink Canvas/Properties/AssemblyInfo.cs @@ -49,5 +49,5 @@ using System.Windows; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.7.15.0")] -[assembly: AssemblyFileVersion("1.7.15.0")] +[assembly: AssemblyVersion("1.7.16.0")] +[assembly: AssemblyFileVersion("1.7.16.0")] diff --git a/UpdateLog.md b/UpdateLog.md index af861394..f899504d 100644 --- a/UpdateLog.md +++ b/UpdateLog.md @@ -100,3 +100,5 @@ ICC CE 1.7.X.X更新日志 99. 修复仅调色盘状态下浮动栏不居中 100. 修复希沃白板查杀与思锐希沃启动器导致的重复启动 101. 新增UIA窗口置顶 +102. 新增新点名窗口 +103. 新增点名快抽