using System; using System.Drawing; using System.Windows.Forms; using TweetDuck.Controls; using TweetDuck.Utils; namespace TweetDuck.Dialogs{ [Flags] enum ControlType{ None = 0, Accept = 1, // triggered by pressing enter when a non-button is focused Cancel = 2, // triggered by closing the dialog without pressing a button Focused = 4 // active control after the dialog is showed } sealed partial class FormMessage : Form{ public const string OK = "OK"; public const string Yes = "Yes"; public const string No = "No"; public const string Cancel = "Cancel"; public const string Retry = "Retry"; public const string Ignore = "Ignore"; public const string Exit = "Exit"; public static bool Information(string caption, string text, string buttonAccept, string buttonCancel = null){ return Show(caption, text, MessageBoxIcon.Information, buttonAccept, buttonCancel); } public static bool Warning(string caption, string text, string buttonAccept, string buttonCancel = null){ return Show(caption, text, MessageBoxIcon.Warning, buttonAccept, buttonCancel); } public static bool Error(string caption, string text, string buttonAccept, string buttonCancel = null){ return Show(caption, text, MessageBoxIcon.Error, buttonAccept, buttonCancel); } public static bool Question(string caption, string text, string buttonAccept, string buttonCancel = null){ return Show(caption, text, MessageBoxIcon.Question, buttonAccept, buttonCancel); } public static bool Show(string caption, string text, MessageBoxIcon icon, string button){ return Show(caption, text, icon, button, null); } public static bool Show(string caption, string text, MessageBoxIcon icon, string buttonAccept, string buttonCancel){ using FormMessage message = new FormMessage(caption, text, icon); if (buttonCancel == null){ message.AddButton(buttonAccept, DialogResult.OK, ControlType.Cancel | ControlType.Focused); } else{ message.AddButton(buttonCancel, DialogResult.Cancel, ControlType.Cancel); message.AddButton(buttonAccept, DialogResult.OK, ControlType.Accept | ControlType.Focused); } return message.ShowDialog() == DialogResult.OK; } // Instance public Button ClickedButton { get; private set; } public bool HasIcon => icon != null; public int ActionPanelY => panelActions.Location.Y; private int ClientWidth{ get => ClientSize.Width; set => ClientSize = new Size(value, ClientSize.Height); } private int ButtonDistance{ get => BrowserUtils.Scale(96, dpiScale); } private readonly Icon icon; private readonly bool isReady; private readonly float dpiScale; private int realFormWidth, minFormWidth; private int buttonCount; private int prevLabelWidth, prevLabelHeight; private bool wasLabelMultiline; public FormMessage(string caption, string text, MessageBoxIcon messageIcon){ InitializeComponent(); this.dpiScale = this.GetDPIScale(); this.prevLabelWidth = labelMessage.Width; this.prevLabelHeight = labelMessage.Height; this.minFormWidth = BrowserUtils.Scale(42, dpiScale); switch(messageIcon){ case MessageBoxIcon.Information: icon = SystemIcons.Information; break; case MessageBoxIcon.Warning: icon = SystemIcons.Warning; break; case MessageBoxIcon.Error: icon = SystemIcons.Error; break; case MessageBoxIcon.Question: icon = SystemIcons.Question; break; default: icon = null; labelMessage.Location = new Point(BrowserUtils.Scale(19, dpiScale), labelMessage.Location.Y); // 19 instead of 9 due to larger height break; } this.isReady = true; this.Text = caption; this.labelMessage.Text = text.Replace("\r", "").Replace("\n", Environment.NewLine); } private void FormMessage_SizeChanged(object sender, EventArgs e){ RecalculateButtonLocation(); } public Button AddButton(string title, ControlType type){ return AddButton(title, DialogResult.OK, type); } public Button AddButton(string title, DialogResult result = DialogResult.OK, ControlType type = ControlType.None){ Button button = new Button{ Anchor = AnchorStyles.Bottom, Font = SystemFonts.MessageBoxFont, Location = new Point(0, 12), Size = new Size(BrowserUtils.Scale(88, dpiScale), BrowserUtils.Scale(26, dpiScale)), TabIndex = 256 - buttonCount, Text = title, UseVisualStyleBackColor = true }; button.Click += (sender, args) => { ClickedButton = (Button)sender; DialogResult = result; Close(); }; panelActions.Controls.Add(button); ++buttonCount; minFormWidth += ButtonDistance; ClientWidth = Math.Max(realFormWidth, minFormWidth); RecalculateButtonLocation(); if (type.HasFlag(ControlType.Accept)){ AcceptButton = button; } if (type.HasFlag(ControlType.Cancel)){ CancelButton = button; } if (type.HasFlag(ControlType.Focused)){ ActiveControl = button; } return button; } public void AddActionControl(Control control){ panelActions.Controls.Add(control); control.Size = new Size(BrowserUtils.Scale(control.Width, dpiScale), BrowserUtils.Scale(control.Height, dpiScale)); minFormWidth += control.Width + control.Margin.Horizontal; ClientWidth = Math.Max(realFormWidth, minFormWidth); } private void RecalculateButtonLocation(){ int dist = ButtonDistance; int start = ClientWidth - dist; for(int index = 0; index < buttonCount; index++){ Control control = panelActions.Controls[index]; control.Location = new Point(start - index * dist, control.Location.Y); } } private void labelMessage_SizeChanged(object sender, EventArgs e){ if (!isReady){ return; } bool isMultiline = labelMessage.Height > labelMessage.MinimumSize.Height; int labelOffset = BrowserUtils.Scale(8, dpiScale); if (isMultiline && !wasLabelMultiline){ labelMessage.Location = new Point(labelMessage.Location.X, labelMessage.Location.Y - labelOffset); prevLabelHeight += labelOffset; } else if (!isMultiline && wasLabelMultiline){ labelMessage.Location = new Point(labelMessage.Location.X, labelMessage.Location.Y + labelOffset); prevLabelHeight -= labelOffset; } realFormWidth = ClientWidth - (icon == null ? BrowserUtils.Scale(50, dpiScale) : 0) + labelMessage.Width - prevLabelWidth; ClientWidth = Math.Max(realFormWidth, minFormWidth); Height += labelMessage.Height - prevLabelHeight; prevLabelWidth = labelMessage.Width; prevLabelHeight = labelMessage.Height; wasLabelMultiline = isMultiline; } protected override void OnPaint(PaintEventArgs e){ if (icon != null){ e.Graphics.DrawIcon(icon, BrowserUtils.Scale(25, dpiScale), 1 + BrowserUtils.Scale(25, dpiScale)); } base.OnPaint(e); } } }