using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Interop; using XP.Common.GeneralForm.ViewModels; using XP.Common.Logging.Interfaces; namespace XP.Common.GeneralForm.Views { /// /// 通用进度条模态窗口,支持线程安全的进度更新和关闭操作 /// public partial class ProgressWindow : Window { #region Win32 API [DllImport("user32.dll")] private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); [DllImport("user32.dll")] private static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable); private const uint SC_CLOSE = 0xF060; private const uint MF_BYCOMMAND = 0x00000000; private const uint MF_GRAYED = 0x00000001; private const uint MF_ENABLED = 0x00000000; #endregion private readonly ProgressWindowViewModel _viewModel; private readonly ILoggerService? _logger; private bool _isClosingByCode; /// /// 构造函数 /// /// 窗口标题 /// 提示信息 /// 是否允许用户关闭窗口 /// 日志服务(可选) public ProgressWindow( string title = "操作进行中", string message = "请稍候...", bool isCancelable = true, ILoggerService? logger = null) { // 创建 ViewModel 并设置为 DataContext _viewModel = new ProgressWindowViewModel(title, message, 0, isCancelable, logger); DataContext = _viewModel; // 保存日志服务引用,用于 View 层日志记录 _logger = logger?.ForModule(); InitializeComponent(); // 继承主窗口图标 if (Application.Current?.MainWindow != null) { Icon = Application.Current.MainWindow.Icon; } // 订阅 Closing 事件,拦截用户手动关闭 Closing += OnWindowClosing; } /// /// 更新进度和提示信息(线程安全,可从任意线程调用) /// /// 提示信息文本 /// 进度值 public void UpdateProgress(string message, double progress) { try { if (Dispatcher.CheckAccess()) { _viewModel.UpdateProgress(message, progress); } else { Dispatcher.Invoke(() => _viewModel.UpdateProgress(message, progress)); } } catch (TaskCanceledException) { // 窗口已关闭时 Dispatcher 调度可能抛出此异常,静默处理 } catch (Exception) { // 其他调度异常静默处理,避免影响调用方 } } /// /// 线程安全关闭窗口(使用 new 关键字隐藏基类 Close 方法,因为 Window.Close() 不是虚方法) /// public new void Close() { try { _isClosingByCode = true; if (Dispatcher.CheckAccess()) { _logger?.Info("进度窗口正在关闭:Title={Title}", _viewModel.Title); base.Close(); } else { Dispatcher.Invoke(() => { _logger?.Info("进度窗口正在关闭:Title={Title}", _viewModel.Title); base.Close(); }); } } catch (TaskCanceledException) { // 窗口已关闭时 Dispatcher 调度可能抛出此异常,静默处理 } catch (Exception) { // 其他调度异常静默处理,避免影响调用方 } } /// /// 窗口源初始化时,根据 IsCancelable 控制关闭按钮状态 /// protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); if (!_viewModel.IsCancelable) { DisableCloseButton(); } } /// /// 拦截窗口关闭事件 /// private void OnWindowClosing(object? sender, CancelEventArgs e) { // 当不可取消且非程序主动关闭时,阻止关闭 if (!_viewModel.IsCancelable && !_isClosingByCode) { e.Cancel = true; } } /// /// 通过 Win32 API 禁用窗口关闭按钮(灰色不可点击) /// private void DisableCloseButton() { var hwnd = new WindowInteropHelper(this).Handle; var hMenu = GetSystemMenu(hwnd, false); if (hMenu != IntPtr.Zero) { EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); } } /// /// 通过 Win32 API 启用窗口关闭按钮 /// private void EnableCloseButton() { var hwnd = new WindowInteropHelper(this).Handle; var hMenu = GetSystemMenu(hwnd, false); if (hMenu != IntPtr.Zero) { EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED); } } } }