using System; using System.Windows; using System.Windows.Media.Animation; using System.Windows.Threading; namespace 自救器呼吸器综合检验仪 { public partial class LoadingOverlayWindow : Window { private static readonly TimeSpan MinimumDisplayDuration = TimeSpan.FromMilliseconds(700); private static readonly TimeSpan DismissAnimationDuration = TimeSpan.FromMilliseconds(240); private readonly DateTime _shownAtUtc; private bool _closeRequested; public LoadingOverlayWindow() { InitializeComponent(); _shownAtUtc = DateTime.UtcNow; } public void AlignTo(Window referenceWindow) { if (referenceWindow == null) { return; } WindowState = WindowState.Normal; double width = referenceWindow.ActualWidth > 0 ? referenceWindow.ActualWidth : referenceWindow.Width; double height = referenceWindow.ActualHeight > 0 ? referenceWindow.ActualHeight : referenceWindow.Height; if (width <= 0 || height <= 0) { Rect restoreBounds = referenceWindow.RestoreBounds; width = restoreBounds.Width > 0 ? restoreBounds.Width : width; height = restoreBounds.Height > 0 ? restoreBounds.Height : height; } Left = referenceWindow.Left; Top = referenceWindow.Top; Width = width; Height = height; } public void MatchTopmost(Window referenceWindow) { if (referenceWindow == null) { return; } Topmost = referenceWindow.Topmost; } public void SetMessage(string title, string subtitle) { if (!string.IsNullOrWhiteSpace(title)) { TitleText.Text = title; } if (!string.IsNullOrWhiteSpace(subtitle)) { SubtitleText.Text = subtitle; } } public void CloseWhenReady() { if (_closeRequested) { return; } _closeRequested = true; TimeSpan remaining = MinimumDisplayDuration - (DateTime.UtcNow - _shownAtUtc); if (remaining <= TimeSpan.Zero) { CloseOverlay(); return; } DispatcherTimer timer = new DispatcherTimer( remaining, DispatcherPriority.Background, OnCloseTimerTick, Dispatcher); timer.Start(); } private void OnCloseTimerTick(object sender, EventArgs e) { DispatcherTimer timer = sender as DispatcherTimer; if (timer != null) { timer.Stop(); timer.Tick -= OnCloseTimerTick; } CloseOverlay(); } private void CloseOverlay() { if (Dispatcher.HasShutdownStarted || Dispatcher.HasShutdownFinished || !IsLoaded) { return; } DoubleAnimation fadeOutAnimation = new DoubleAnimation { From = Opacity, To = 0, Duration = new Duration(DismissAnimationDuration), FillBehavior = FillBehavior.Stop }; fadeOutAnimation.Completed += (sender, args) => { if (Dispatcher.HasShutdownStarted || Dispatcher.HasShutdownFinished || !IsLoaded) { return; } Close(); }; BeginAnimation(OpacityProperty, fadeOutAnimation); } } }