namespace MatrixImageEditor; internal enum AppDialogIcon { Information, Warning, Error, } internal sealed class AppDialog : Form { private static readonly Size PreferredLogicalSize = new(640, 320); private static readonly Size MinimumLogicalSize = new(520, 260); private readonly Screen initialScreen; private AppDialog(IWin32Window? owner, string message, string title, MessageBoxButtons buttons, AppDialogIcon icon) { initialScreen = owner is null ? Screen.PrimaryScreen! : Screen.FromHandle(owner.Handle); Text = title; AutoScaleMode = AutoScaleMode.Dpi; Font = new Font("Microsoft YaHei UI", 10F); FormBorderStyle = FormBorderStyle.Sizable; StartPosition = FormStartPosition.Manual; ShowInTaskbar = false; MinimizeBox = false; MaximizeBox = false; var body = new TableLayoutPanel { Dock = DockStyle.Fill, Padding = new Padding(24), ColumnCount = 2, RowCount = 2, }; body.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); body.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); body.RowStyles.Add(new RowStyle(SizeType.Percent, 100)); body.RowStyles.Add(new RowStyle(SizeType.AutoSize)); var picture = new PictureBox { Image = GetIcon(icon).ToBitmap(), SizeMode = PictureBoxSizeMode.CenterImage, Size = new Size(64, 64), Margin = new Padding(0, 0, 20, 0), Anchor = AnchorStyles.Top, }; var text = new TextBox { Text = message, ReadOnly = true, Multiline = true, WordWrap = true, ScrollBars = ScrollBars.Vertical, Dock = DockStyle.Fill, BackColor = SystemColors.Window, BorderStyle = BorderStyle.FixedSingle, Margin = new Padding(0), ShortcutsEnabled = true, }; var actions = new FlowLayoutPanel { Dock = DockStyle.Fill, AutoSize = true, FlowDirection = FlowDirection.RightToLeft, WrapContents = false, Margin = new Padding(0, 20, 0, 0), }; if (buttons == MessageBoxButtons.YesNo) { var no = Button("否", DialogResult.No); var yes = Button("是", DialogResult.Yes); actions.Controls.Add(no); actions.Controls.Add(yes); AcceptButton = yes; CancelButton = no; } else { var ok = Button("确定", DialogResult.OK); actions.Controls.Add(ok); AcceptButton = ok; CancelButton = ok; } body.Controls.Add(picture, 0, 0); body.Controls.Add(text, 1, 0); body.Controls.Add(actions, 0, 1); body.SetColumnSpan(actions, 2); Controls.Add(body); } public static DialogResult Show(IWin32Window? owner, string message, string title, MessageBoxButtons buttons, AppDialogIcon icon) { using var dialog = new AppDialog(owner, message, title, buttons, icon); return owner is null ? dialog.ShowDialog() : dialog.ShowDialog(owner); } public static void Information(IWin32Window? owner, string message, string title) => Show(owner, message, title, MessageBoxButtons.OK, AppDialogIcon.Information); public static void Error(IWin32Window? owner, string message, string title) => Show(owner, message, title, MessageBoxButtons.OK, AppDialogIcon.Error); public static DialogResult Confirm(IWin32Window? owner, string message, string title) => Show(owner, message, title, MessageBoxButtons.YesNo, AppDialogIcon.Warning); protected override void OnShown(EventArgs eventArgs) { base.OnShown(eventArgs); ResponsiveLayout.FitAndCenter(this, PreferredLogicalSize, MinimumLogicalSize, 0.8, initialScreen); } protected override void OnDpiChanged(DpiChangedEventArgs eventArgs) { base.OnDpiChanged(eventArgs); BeginInvoke(() => ResponsiveLayout.FitAndCenter(this, PreferredLogicalSize, MinimumLogicalSize, 0.8)); } private static Button Button(string text, DialogResult result) => new() { Text = text, DialogResult = result, AutoSize = true, MinimumSize = new Size(110, 38), Margin = new Padding(10, 0, 0, 0), }; private static Icon GetIcon(AppDialogIcon icon) => icon switch { AppDialogIcon.Error => SystemIcons.Error, AppDialogIcon.Warning => SystemIcons.Warning, _ => SystemIcons.Information, }; }