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/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 48a621a3..c9d0d120 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -3249,6 +3249,15 @@ FontWeight="Bold" Toggled="ToggleSwitchShowRandomAndSingleDraw_Toggled" /> + + + + @@ -3299,6 +3308,62 @@ FontFamily="Consolas" Text="{Binding ElementName=RandWindowOnceMaxStudentsSlider, Path=Value, Converter={StaticResource IntNumberToString}}" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /// 显示快抽悬浮按钮 + /// + 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_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index 69ff3c99..86d0cd27 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -1085,11 +1085,20 @@ namespace Ink_Canvas AnimationsHelper.HideWithSlideAndFade(BoardBorderTools); AnimationsHelper.HideWithSlideAndFade(BoardImageOptionsPanel); - var randWindow = new RandWindow(Settings); - randWindow.Show(); + // 根据设置决定使用哪个点名窗口 + if (Settings.RandSettings.UseNewRollCallUI) + { + // 使用新点名UI - 随机抽模式 + new NewStyleRollCallWindow(Settings, false).ShowDialog(); + } + else + { + // 使用默认的随机点名窗口 + var randWindow = new RandWindow(Settings); + randWindow.Show(); - // 使用延迟确保窗口完全显示后再强制置顶 - randWindow.Dispatcher.BeginInvoke(new Action(() => + // 使用延迟确保窗口完全显示后再强制置顶 + 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..4624ac44 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; @@ -2740,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 c9699bb8..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; @@ -886,6 +887,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) @@ -915,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/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/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..395ea46d 100644 --- a/Ink Canvas/Resources/Settings.cs +++ b/Ink Canvas/Resources/Settings.cs @@ -650,6 +650,16 @@ 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; + [JsonProperty("enableQuickDraw")] + public bool EnableQuickDraw { get; set; } = true; } public class CustomPickNameBackground 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 @@ - - + + 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"> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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. 新增点名快抽