using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Shapes; using System.Windows.Media.Animation; namespace Ink_Canvas.Windows { public partial class MinimizedTimerWindow : Window { private TimerControl parentControl; private System.Timers.Timer updateTimer; private bool isMouseOver = false; private bool isDragging = false; private Point lastMousePosition; public MinimizedTimerWindow(TimerControl parent) { InitializeComponent(); parentControl = parent; var mainWindow = Application.Current.MainWindow as MainWindow; if (mainWindow != null) { this.Left = mainWindow.Left; this.Top = mainWindow.Top; } ScaleWindowForResolution(); updateTimer = new System.Timers.Timer(100); updateTimer.Elapsed += UpdateTimer_Elapsed; updateTimer.Start(); parentControl.TimerCompleted += ParentWindow_TimerCompleted; // 应用主题 ApplyTheme(); // 确保窗口置顶 Loaded += MinimizedTimerWindow_Loaded; } private void MinimizedTimerWindow_Loaded(object sender, RoutedEventArgs e) { // 使用延迟确保窗口完全加载后再应用置顶 Dispatcher.BeginInvoke(new Action(() => { ApplyTopmost(); }), System.Windows.Threading.DispatcherPriority.Loaded); } #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 void ApplyTopmost() { try { var hwnd = new WindowInteropHelper(this).Handle; if (hwnd == IntPtr.Zero) return; // 设置WPF的Topmost属性 Topmost = true; // 使用Win32 API强制置顶 int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE); SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST); // 使用SetWindowPos确保窗口在最顶层 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"应用最小化窗口置顶失败: {ex.Message}"); } } #endregion /// /// 根据屏幕分辨率和 DPI 缩放窗口大小(保持原始尺寸,使用Transform缩放) /// private void ScaleWindowForResolution() { try { // 获取屏幕尺寸(考虑 DPI 缩放) double screenWidth = SystemParameters.PrimaryScreenWidth; double screenHeight = SystemParameters.PrimaryScreenHeight; // 基准分辨率(1920x1080) const double baseWidth = 1920.0; const double baseHeight = 1080.0; // 计算缩放比例(使用较小的比例以保持比例) double scaleX = screenWidth / baseWidth; double scaleY = screenHeight / baseHeight; double scale = Math.Min(scaleX, scaleY); // 限制最小和最大缩放,避免过小或过大 scale = Math.Max(0.5, Math.Min(2.0, scale)); // 应用缩放变换到整个窗口内容 var scaleTransform = this.FindName("WindowScaleTransform") as ScaleTransform; if (scaleTransform != null) { scaleTransform.ScaleX = scale; scaleTransform.ScaleY = scale; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"缩放窗口大小时出错: {ex.Message}"); } } private void UpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (parentControl != null) { Application.Current.Dispatcher.Invoke(() => { if (ShouldCloseWindow()) { this.Close(); return; } UpdateTimeDisplay(); }); } } private bool ShouldCloseWindow() { if (parentControl == null) return true; if (MainWindow.Settings.RandSettings?.EnableOvertimeCountUp == true) { if (parentControl.IsTimerRunning) { return false; } var remainingTime = parentControl.GetRemainingTime(); if (remainingTime.HasValue && remainingTime.Value.TotalSeconds < 0) { return false; } return true; } else { return !parentControl.IsTimerRunning; } } private void UpdateTimeDisplay() { if (parentControl == null) return; var remainingTime = parentControl.GetRemainingTime(); if (remainingTime.HasValue) { var timeSpan = remainingTime.Value; bool isOvertimeMode = timeSpan.TotalSeconds < 0; bool shouldShowRed = isOvertimeMode && MainWindow.Settings.RandSettings?.EnableOvertimeRedText == true; int hours, minutes, seconds; if (isOvertimeMode) { var totalTimeSpan = parentControl.GetTotalTimeSpan(); if (totalTimeSpan.HasValue) { var elapsedTime = parentControl.GetElapsedTime(); if (elapsedTime.HasValue) { var overtimeSpan = elapsedTime.Value - totalTimeSpan.Value; hours = (int)overtimeSpan.TotalHours; minutes = overtimeSpan.Minutes; seconds = overtimeSpan.Seconds; } else { hours = 0; minutes = 0; seconds = 0; } } else { hours = 0; minutes = 0; seconds = 0; } } else { hours = (int)timeSpan.TotalHours; minutes = timeSpan.Minutes; seconds = timeSpan.Seconds; } SetDigitDisplay("MinHour1Display", Math.Abs(hours / 10) % 10, shouldShowRed); SetDigitDisplay("MinHour2Display", (hours % 10 + 10) % 10, shouldShowRed); SetDigitDisplay("MinMinute1Display", minutes / 10, shouldShowRed); SetDigitDisplay("MinMinute2Display", minutes % 10, shouldShowRed); SetDigitDisplay("MinSecond1Display", seconds / 10, shouldShowRed); SetDigitDisplay("MinSecond2Display", seconds % 10, shouldShowRed); SetColonDisplay(shouldShowRed); } } private void ParentWindow_TimerCompleted(object sender, EventArgs e) { Application.Current.Dispatcher.Invoke(() => { this.Close(); }); } private void SetDigitDisplay(string pathName, int digit, bool isRed = false) { var path = this.FindName(pathName) as Path; if (path != null) { string resourceKey = $"Digit{digit}"; var geometry = this.FindResource(resourceKey) as Geometry; if (geometry != null) { path.Data = geometry; } // 设置颜色 if (isRed) { path.Fill = Brushes.Red; } else { var defaultBrush = this.FindResource("NewTimerWindowDigitForeground") as Brush; if (defaultBrush != null) { path.Fill = defaultBrush; } else { bool isLightTheme = IsLightTheme(); path.Fill = isLightTheme ? Brushes.Black : Brushes.White; } } } } /// /// 设置最小化窗口冒号显示颜色 /// /// 是否显示为红色 private void SetColonDisplay(bool isRed = false) { var colon1 = this.FindName("MinColon1Display") as TextBlock; var colon2 = this.FindName("MinColon2Display") as TextBlock; if (colon1 != null) { if (isRed) { colon1.Foreground = Brushes.Red; } else { var defaultBrush = this.FindResource("NewTimerWindowDigitForeground") as Brush; if (defaultBrush != null) { colon1.Foreground = defaultBrush; } else { bool isLightTheme = IsLightTheme(); colon1.Foreground = isLightTheme ? Brushes.Black : Brushes.White; } } } if (colon2 != null) { if (isRed) { colon2.Foreground = Brushes.Red; } else { var defaultBrush = this.FindResource("NewTimerWindowDigitForeground") as Brush; if (defaultBrush != null) { colon2.Foreground = defaultBrush; } else { bool isLightTheme = IsLightTheme(); colon2.Foreground = isLightTheme ? Brushes.Black : Brushes.White; } } } } private void ApplyTheme() { try { bool isLightTheme = IsLightTheme(); if (!isLightTheme) { SetDarkThemeBorder(); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"应用主题时出错: {ex.Message}"); } } private bool IsLightTheme() { try { var mainWindow = Application.Current.MainWindow as MainWindow; if (mainWindow != null) { var currentModeField = mainWindow.GetType().GetField("currentMode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (currentModeField != null) { var currentMode = currentModeField.GetValue(mainWindow); return currentMode?.ToString() == "Light"; } } } catch { // 如果获取主题失败,默认使用浅色主题 } return true; } // 设置深色主题下的灰色边框 private void SetDarkThemeBorder() { try { // 找到Border元素并设置灰色边框 var border = this.FindName("MainBorder") as Border; if (border != null) { border.BorderBrush = new SolidColorBrush(Color.FromRgb(64, 64, 64)); } } catch { } } private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // 记录点击时间 lastClickTime = DateTime.Now; // 开始拖动 isDragging = true; lastMousePosition = e.GetPosition(this); this.CaptureMouse(); } private void Window_MouseMove(object sender, MouseEventArgs e) { if (isDragging) { var currentPosition = e.GetPosition(this); var deltaX = currentPosition.X - lastMousePosition.X; var deltaY = currentPosition.Y - lastMousePosition.Y; this.Left += deltaX; this.Top += deltaY; } } private void Window_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (isDragging) { isDragging = false; this.ReleaseMouseCapture(); var clickDuration = DateTime.Now - lastClickTime; if (clickDuration.TotalMilliseconds < 200) { this.Close(); } } } private DateTime lastClickTime = DateTime.Now; private void Window_MouseEnter(object sender, MouseEventArgs e) { isMouseOver = true; // 鼠标进入时显示关闭按钮 if (CloseButton != null) { CloseButton.Opacity = 1.0; } } private void Window_MouseLeave(object sender, MouseEventArgs e) { isMouseOver = false; // 鼠标离开时隐藏关闭按钮 if (CloseButton != null) { CloseButton.Opacity = 0.7; } } private void CloseButton_Click(object sender, RoutedEventArgs e) { if (parentControl != null) { parentControl.StopTimer(); } this.Close(); } protected override void OnClosed(EventArgs e) { if (parentControl != null) { parentControl.TimerCompleted -= ParentWindow_TimerCompleted; } // 清理资源 if (updateTimer != null) { updateTimer.Stop(); updateTimer.Dispose(); } base.OnClosed(e); } } }