using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Windows.Threading; using WPFluent.Interop; namespace WPFluent.Controls; public static class PendingBox { public static IPendingHandler Show(string? message = null, string? title = null, bool isShowCancel = false, bool closeOnCanceled = true) { return Show(null, message, title, isShowCancel, closeOnCanceled); } public static IPendingHandler Show(Window? owner, string? message, string? title = null, bool isShowCancel = false, bool closeOnCanceled = true) { return ShowCore(owner, message, title, isShowCancel, closeOnCanceled); } [SuppressMessage("Performance", "CA1859:Use concrete types when possible for improved performance")] [SuppressMessage("CodeQuality", "IDE0079:Remove unnecessary suppression")] private static IPendingHandler ShowCore(Window? owner, string? message, string? title, bool isShowCancel, bool closeOnCanceled = true) { owner ??= Application.Current.Windows.OfType().FirstOrDefault(window => window.IsActive) ?? Application.Current.MainWindow; Dispatcher dispatcher = owner?.Dispatcher ?? Application.Current.Dispatcher; return dispatcher.Invoke(() => { PendingBoxDialog dialog = new() { Owner = owner, Title = title ?? string.Empty, Message = message ?? ("加载中" + "..."), IsShowCancel = isShowCancel, WindowStartupLocation = owner is null ? WindowStartupLocation.CenterScreen : WindowStartupLocation.CenterOwner }; PendingHandler pending = new(dialog) { CloseOnCanceled = closeOnCanceled, }; dialog.Closing += (_, e) => { if (!e.Cancel) { User32.SetForegroundWindow(new WindowInteropHelper(owner).Handle); } }; dialog.Closed += (s, e) => { pending.RaiseClosedEvent(s, e); User32.EnableWindow(new WindowInteropHelper(owner).Handle, true); User32.SetForegroundWindow(new WindowInteropHelper(owner).Handle); }; dialog.Canceled += (s, e) => { pending.RaiseCanceledEvent(s, e); User32.EnableWindow(new WindowInteropHelper(owner).Handle, true); }; User32.EnableWindow(new WindowInteropHelper(owner).Handle, false); dialog.Show(); return pending; }); } [SuppressMessage("Performance", "CA1859:Use concrete types when possible for improved performance")] [SuppressMessage("Style", "IDE0060:Remove unused parameter")] [SuppressMessage("CodeQuality", "IDE0079:Remove unnecessary suppression")] private static IPendingHandler ShowCoreAsync(Window? owner, string? message, string? title, bool isShowCancel, bool closeOnCanceled = true) { Point? center = null; try { owner?.Dispatcher.Invoke(() => { Rect rect = new(); User32.GetWindowRect(new WindowInteropHelper(owner).Handle, out rect); Point p = new(rect.Left + (int)((rect.Right - rect.Left) / 2d), rect.Top + (int)((rect.Bottom - rect.Top) / 2d)); center = new(p.X, p.Y); }); } catch { /// } PendingBoxDialog dialog = new() { Title = title ?? string.Empty, Message = message ?? ("加载中" + "..."), IsShowCancel = isShowCancel, WindowStartupLocation = WindowStartupLocation.CenterScreen, }; PendingHandlerAsync pending = new(dialog); dialog.Closing += (_, e) => { if (!e.Cancel) { User32.SetForegroundWindow(new WindowInteropHelper(owner).Handle); } }; dialog.Closed += (s, e) => { pending.RaiseClosedEvent(s, e); pending.Close(); }; dialog.Canceled += (s, e) => { pending.RaiseCanceledEvent(s, e); pending.Close(); }; if (center != null) { dialog.Loaded += (_, _) => { try { LayoutHelper.MoveWindowCenter(dialog, (Point)center); } catch { /// } }; } return pending; } } file static class LayoutHelper { public static void MoveWindowCenter(Window window, Point center) { if (window == null) { return; } nint hwnd = new WindowInteropHelper(window).Handle; if (hwnd == IntPtr.Zero) { return; } Rect rect = default; User32.GetWindowRect(hwnd, out rect); nint monitorHandle = User32.MonitorFromWindow(hwnd, User32.MonitorDefaultTo.Nearest); User32.MONITORINFO monitorInfo = new() { cbSize = Marshal.SizeOf() }; User32.GetMonitorInfo(monitorHandle, ref monitorInfo); Rect screen = monitorInfo.rcMonitor; (double x, double y) = ((int)center.X, (int)center.Y); (double w, double h) = (rect.Right - rect.Left, rect.Bottom - rect.Top); (x, y) = ((int)(x - w / 2d), (int)(y - h / 2d)); if (x + w > screen.Right) { x = screen.Right - w; } else if (x - w < screen.Left) { x = screen.Left + w; } if (y + h > screen.Bottom) { y = screen.Bottom - h; } else if (y - h < screen.Top) { y = screen.Top + h; } User32.MoveWindow(hwnd, x, y, w, h, false); } }