2025-04-24 20:56:44 +08:00
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2025-02-10 20:53:40 +08:00
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
using System.Windows.Threading;
|
|
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
using WPFluent.Interop;
|
|
|
|
|
|
|
2025-02-10 20:53:40 +08:00
|
|
|
|
|
|
|
|
|
|
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<Window>().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)
|
|
|
|
|
|
{
|
2025-04-24 20:56:44 +08:00
|
|
|
|
User32.SetForegroundWindow(new WindowInteropHelper(owner).Handle);
|
2025-02-10 20:53:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
dialog.Closed += (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
pending.RaiseClosedEvent(s, e);
|
2025-04-24 20:56:44 +08:00
|
|
|
|
User32.EnableWindow(new WindowInteropHelper(owner).Handle, true);
|
|
|
|
|
|
User32.SetForegroundWindow(new WindowInteropHelper(owner).Handle);
|
2025-02-10 20:53:40 +08:00
|
|
|
|
};
|
|
|
|
|
|
dialog.Canceled += (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
pending.RaiseCanceledEvent(s, e);
|
2025-04-24 20:56:44 +08:00
|
|
|
|
User32.EnableWindow(new WindowInteropHelper(owner).Handle, true);
|
2025-02-10 20:53:40 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
User32.EnableWindow(new WindowInteropHelper(owner).Handle, false);
|
2025-02-10 20:53:40 +08:00
|
|
|
|
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();
|
2025-04-24 20:56:44 +08:00
|
|
|
|
User32.GetWindowRect(new WindowInteropHelper(owner).Handle, out rect);
|
2025-02-10 20:53:40 +08:00
|
|
|
|
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)
|
|
|
|
|
|
{
|
2025-04-24 20:56:44 +08:00
|
|
|
|
User32.SetForegroundWindow(new WindowInteropHelper(owner).Handle);
|
2025-02-10 20:53:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
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;
|
2025-04-24 20:56:44 +08:00
|
|
|
|
User32.GetWindowRect(hwnd, out rect);
|
2025-02-10 20:53:40 +08:00
|
|
|
|
|
|
|
|
|
|
nint monitorHandle = User32.MonitorFromWindow(hwnd, User32.MonitorDefaultTo.Nearest);
|
|
|
|
|
|
User32.MONITORINFO monitorInfo = new()
|
|
|
|
|
|
{
|
|
|
|
|
|
cbSize = Marshal.SizeOf<User32.MONITORINFO>()
|
|
|
|
|
|
};
|
2025-04-24 20:56:44 +08:00
|
|
|
|
User32.GetMonitorInfo(monitorHandle, ref monitorInfo);
|
2025-02-10 20:53:40 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
User32.MoveWindow(hwnd, x, y, w, h, false);
|
2025-02-10 20:53:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|