mirror of https://github.com/dahall/Vanara.git
1410 lines
47 KiB
C#
1410 lines
47 KiB
C#
/*
|
|
* Copyright © 2015 David Hall
|
|
*
|
|
* Design Notes:-
|
|
* --------------
|
|
* TableLayoutPanels are the containers to hold the sub sections
|
|
* (FlowLayoutPanels), while the FlowLayoutPanels holds and performs the layout
|
|
* of the controls:
|
|
*
|
|
* - Main area (tableLayoutPanelMainArea):
|
|
* + Main icon (pictureBoxMainIcon).
|
|
* + Main information (flowLayoutPanelMainAreaControls).
|
|
* + Content (flowLayoutPanelMainAreaControls).
|
|
* + Expanded information (flowLayoutPanelMainAreaControls).
|
|
* + Progressbar (flowLayoutPanelMainAreaControls).
|
|
* + Radio buttons (flowLayoutPanelMainAreaControls).
|
|
* + Command links. (flowLayoutPanelMainAreaControls).
|
|
* - Sub area (tableLayoutPanelSubArea).
|
|
* + Expand/Collapse button (flowLayoutPanelSubAreaControls).
|
|
* + Verification checkbox (flowLayoutPanelSubAreaControls).
|
|
* + Custom/Common buttons (flowLayoutPanelsSubAreaButtons).
|
|
* - Footer area (tableLayoutPanelFooterArea).
|
|
* + Footer text (flowLayoutFooterAreaText).
|
|
* - Footer expanded information (flowLayoutFooterExpandedInformationArea).
|
|
* + Expanded information (flowLayoutPanelFooterExpandedInformationAreaText).
|
|
*
|
|
* Limitations:
|
|
* - Form issues:
|
|
* + No form icon when TaskDialog.CanBeMinimized is true.
|
|
* * Note: .Net does not provide an easy way to convert bitmap to icon.
|
|
* + Might not support right to left layouts.
|
|
* + "Retry" button will be added in a wrong order.
|
|
* + Command links has no accelerator key support.
|
|
* * Note: CommandLink class draws the text instead of letting the button
|
|
* handle the text.
|
|
*
|
|
* References:
|
|
* - http://www.codeproject.com/KB/vista/Vista_TaskDialog_Wrapper.aspx
|
|
* - http://www.codeproject.com/Articles/21276/Vista-TaskDialog-Wrapper-and-Emulator
|
|
* - http://www.codeproject.com/Articles/17026/TaskDialog-for-WinForms
|
|
*
|
|
* Revision Control:-
|
|
* ------------------
|
|
* Created On: 2007 November 26
|
|
* Major updates: 2015 Nov 6
|
|
*/
|
|
|
|
#if TASKDIALOG_EMULATE
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Windows.Forms;
|
|
using static Vanara.PInvoke;
|
|
using static Vanara.PInvoke;
|
|
using static Vanara.PInvoke;
|
|
|
|
namespace Vanara.Windows.Forms
|
|
{
|
|
/// <summary>
|
|
/// Tries to emulate the Task Dialog. Form will be called when the call to
|
|
/// Task Dialog is not supported.
|
|
/// </summary>
|
|
internal class EmulateTaskDialog : Form
|
|
{
|
|
private const int hPadding = 10;
|
|
private System.ComponentModel.IContainer components;
|
|
private Button defaultButton;
|
|
private RadioButton defaultRadioButton;
|
|
private EmulateExpInfoButton expandedInfoButton;
|
|
private FlowLayoutPanel flowLayoutPanelFooterAreaText;
|
|
private FlowLayoutPanel flowLayoutPanelFooterExpandedInformationText;
|
|
private FlowLayoutPanel flowLayoutPanelMainAreaControls;
|
|
private FlowLayoutPanel flowLayoutPanelSubAreaButtons;
|
|
private FlowLayoutPanel flowLayoutPanelSubAreaControls;
|
|
private bool isExpanded = true;
|
|
private LinkLabel linkLabelExpandedInformation;
|
|
private PictureBox pictureBoxFooterAreaIcon;
|
|
private PictureBox pictureBoxMainAreaIcon;
|
|
private ProgressBar progressBar;
|
|
private Panel tableLayoutPanel1;
|
|
private Panel tableLayoutPanel2;
|
|
private Panel tableLayoutPanel3;
|
|
private Panel tableLayoutPanel4;
|
|
private TableLayoutPanel tableLayoutPanelFooterArea;
|
|
private TableLayoutPanel tableLayoutPanelFooterExpandedInformationArea;
|
|
private TableLayoutPanel tableLayoutPanelMainArea;
|
|
private TableLayoutPanel tableLayoutPanelSubArea;
|
|
private readonly TaskDialog taskDialog;
|
|
private readonly Dictionary<int, Button> taskDialogButtons = new Dictionary<int, Button>();
|
|
private Timer timer;
|
|
private uint timerTickCount;
|
|
|
|
public EmulateTaskDialog(TaskDialog newTaskDialog)
|
|
{
|
|
// http://dotnetperls.com/Content/Segoe-Tahoma-Windows-Forms.aspx
|
|
// http://www.codeproject.com/KB/cs/AdjustingFontAndLayout.aspx
|
|
// For some discussion about setting program fonts.
|
|
Font = SystemFonts.MessageBoxFont;
|
|
|
|
InitializeComponent();
|
|
|
|
taskDialog = newTaskDialog;
|
|
|
|
Reset();
|
|
}
|
|
|
|
public int TaskDialogRadioButtonResult { get; private set; }
|
|
|
|
public int TaskDialogResult { get; private set; }
|
|
|
|
public bool TaskDialogVerificationFlagChecked { get; private set; }
|
|
|
|
/// <summary>
|
|
/// This will return the formatted contents of the form. Useful when
|
|
/// the user press "ctrl + c" on the form.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override string ToString()
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
sb.AppendLine("[Window Title]");
|
|
sb.AppendLine(Text);
|
|
|
|
if (!string.IsNullOrEmpty(taskDialog.MainInstruction))
|
|
{
|
|
sb.AppendLine("");
|
|
sb.AppendLine("[Main Instruction]");
|
|
sb.AppendLine(taskDialog.MainInstruction);
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(taskDialog.Content))
|
|
{
|
|
sb.AppendLine("");
|
|
sb.AppendLine("[Content]");
|
|
sb.AppendLine(taskDialog.Content);
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(taskDialog.ExpandedInformation) && !taskDialog.ExpandFooterArea)
|
|
{
|
|
sb.AppendLine("");
|
|
sb.AppendLine("[Expanded Information]");
|
|
sb.AppendLine(taskDialog.ExpandedInformation);
|
|
}
|
|
|
|
// There should be a max of two controls here.
|
|
foreach (Control control in flowLayoutPanelSubAreaControls.Controls)
|
|
{
|
|
if (control is EmulateExpInfoButton)
|
|
{
|
|
// Should be the expand/collapse button.
|
|
sb.AppendLine("");
|
|
sb.Append((isExpanded ? "[^] " : "[v] "));
|
|
sb.Append(control.Text);
|
|
sb.Append(" ");
|
|
}
|
|
|
|
var box = control as CheckBox;
|
|
if (box == null) continue;
|
|
sb.Append(box.Checked ? "[X] " : "[ ] ");
|
|
sb.Append(control.Text);
|
|
sb.Append(" ");
|
|
}
|
|
|
|
// Should contains only buttons. As the layout direction is right
|
|
// to left, need to get by reverse order. Dictionary does not keep
|
|
// the order of buttons added in. So this work around is used.
|
|
for (var i = flowLayoutPanelSubAreaButtons.Controls.Count - 1; i >= 0; i--)
|
|
{
|
|
var control = flowLayoutPanelSubAreaButtons.Controls[i];
|
|
if (!(control is Button)) continue;
|
|
sb.Append("[" + control.Text + "]");
|
|
sb.Append(" ");
|
|
}
|
|
|
|
sb.AppendLine("");
|
|
|
|
if (!string.IsNullOrEmpty(taskDialog.Footer))
|
|
{
|
|
sb.AppendLine("");
|
|
sb.AppendLine("[Footer]");
|
|
sb.AppendLine(taskDialog.Footer);
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(taskDialog.ExpandedInformation) && taskDialog.ExpandFooterArea)
|
|
{
|
|
sb.AppendLine("");
|
|
sb.AppendLine("[Expanded Information]");
|
|
sb.AppendLine(taskDialog.ExpandedInformation);
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
internal void EnableButton(int buttonId, bool enable)
|
|
{
|
|
Button btn;
|
|
if (taskDialogButtons.TryGetValue(buttonId, out btn))
|
|
{
|
|
btn.Enabled = enable;
|
|
btn.Invalidate();
|
|
}
|
|
}
|
|
|
|
internal void EnableRadioButton(int buttonId, bool enable)
|
|
{
|
|
foreach (var c in flowLayoutPanelMainAreaControls.Controls)
|
|
{
|
|
var r = c as RadioButton;
|
|
if (r != null && int.Equals(r.Tag, buttonId))
|
|
{
|
|
r.Enabled = enable;
|
|
r.Invalidate();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void PerformButtonClick(int buttonId)
|
|
{
|
|
Button btn;
|
|
if (taskDialogButtons.TryGetValue(buttonId, out btn))
|
|
btn.PerformClick();
|
|
}
|
|
|
|
internal void PerformRadioButtonClick(int buttonId)
|
|
{
|
|
foreach (var c in flowLayoutPanelMainAreaControls.Controls)
|
|
{
|
|
var r = c as RadioButton;
|
|
if (r != null && int.Equals(r.Tag, buttonId))
|
|
r.PerformClick();
|
|
}
|
|
}
|
|
|
|
internal void PerformVerificationClick(bool checkedState, bool setKeyboardFocusToCheckBox)
|
|
{
|
|
if (flowLayoutPanelSubAreaControls.Controls.ContainsKey("VerificationText"))
|
|
{
|
|
var cb = (CheckBox)flowLayoutPanelSubAreaControls.Controls["VerificationText"];
|
|
cb.Checked = checkedState;
|
|
if (setKeyboardFocusToCheckBox)
|
|
cb.Focus();
|
|
}
|
|
}
|
|
|
|
internal void SetButtonElevationRequiredState(int buttonId, bool required)
|
|
{
|
|
Button btn;
|
|
if (taskDialogButtons.TryGetValue(buttonId, out btn))
|
|
{
|
|
var link = btn as CommandLink;
|
|
if (link != null)
|
|
{
|
|
link.ShowShield = required;
|
|
}
|
|
else if (Environment.OSVersion.Version.Major >= 6)
|
|
{
|
|
btn.FlatStyle = required ? FlatStyle.System : FlatStyle.Standard;
|
|
SendMessage(btn.Handle, (int)ButtonMessage.BCM_SETSHIELD, 0, required ? 1 : 0);
|
|
}
|
|
btn.Invalidate();
|
|
}
|
|
}
|
|
|
|
internal void SetCommonIcon(TaskDialogIconElement elem, TaskDialogIcon icon)
|
|
{
|
|
switch (elem)
|
|
{
|
|
case TaskDialogIconElement.TDIE_ICON_MAIN:
|
|
SetMainIcon(icon);
|
|
break;
|
|
|
|
case TaskDialogIconElement.TDIE_ICON_FOOTER:
|
|
SetFooterIcon(icon);
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
Invalidate();
|
|
}
|
|
|
|
internal void SetElementText(TaskDialogElement elem, string text)
|
|
{
|
|
switch (elem)
|
|
{
|
|
case TaskDialogElement.TDE_CONTENT:
|
|
if (flowLayoutPanelMainAreaControls.Controls.ContainsKey("Content"))
|
|
flowLayoutPanelMainAreaControls.Controls["Content"].Text = text;
|
|
break;
|
|
|
|
case TaskDialogElement.TDE_EXPANDED_INFORMATION:
|
|
if (flowLayoutPanelMainAreaControls.Controls.ContainsKey("ExpandedInformation"))
|
|
flowLayoutPanelMainAreaControls.Controls["ExpandedInformation"].Text = text;
|
|
if (flowLayoutPanelFooterExpandedInformationText.Controls.ContainsKey("ExpandedInformation"))
|
|
flowLayoutPanelFooterExpandedInformationText.Controls["ExpandedInformation"].Text = text;
|
|
break;
|
|
|
|
case TaskDialogElement.TDE_FOOTER:
|
|
if (flowLayoutPanelFooterAreaText.Controls.ContainsKey("Footer"))
|
|
flowLayoutPanelFooterAreaText.Controls["Footer"].Text = text;
|
|
break;
|
|
|
|
case TaskDialogElement.TDE_MAIN_INSTRUCTION:
|
|
if (flowLayoutPanelMainAreaControls.Controls.ContainsKey("MainInstruction"))
|
|
flowLayoutPanelMainAreaControls.Controls["MainInstruction"].Text = text;
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
Invalidate();
|
|
}
|
|
|
|
internal void SetIcon(TaskDialogIconElement elem, Icon icon)
|
|
{
|
|
switch (elem)
|
|
{
|
|
case TaskDialogIconElement.TDIE_ICON_MAIN:
|
|
SetMainIcon(icon);
|
|
break;
|
|
|
|
case TaskDialogIconElement.TDIE_ICON_FOOTER:
|
|
SetFooterIcon(icon);
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
Invalidate();
|
|
}
|
|
|
|
internal void SetMarqueeProgressBar(bool v)
|
|
{
|
|
if (progressBar != null)
|
|
{
|
|
progressBar.Style = v ? ProgressBarStyle.Marquee : ProgressBarStyle.Continuous;
|
|
progressBar.Invalidate();
|
|
}
|
|
}
|
|
|
|
internal void SetProgressBarRange(int min, int max)
|
|
{
|
|
if (progressBar != null)
|
|
{
|
|
progressBar.Minimum = min;
|
|
progressBar.Maximum = max;
|
|
progressBar.Invalidate();
|
|
}
|
|
}
|
|
|
|
internal void SetProgressBarState(ProgressBarState value)
|
|
{
|
|
if (progressBar != null && Environment.OSVersion.Version.Major >= 6)
|
|
{
|
|
const uint PBM_SETSTATE = 1040;
|
|
SendMessage(progressBar.Handle, PBM_SETSTATE, (int)value, 0);
|
|
progressBar.Invalidate();
|
|
}
|
|
}
|
|
|
|
internal void SetProgressBarValue(int value)
|
|
{
|
|
if (progressBar == null) return;
|
|
progressBar.Value = value;
|
|
progressBar.Invalidate();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clean up any resources being used.
|
|
/// </summary>
|
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
components?.Dispose();
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
protected override void OnClosed(EventArgs e)
|
|
{
|
|
base.OnClosed(e);
|
|
taskDialog.OnClosed();
|
|
}
|
|
|
|
protected override void OnKeyDown(KeyEventArgs e)
|
|
{
|
|
if (taskDialog.AllowDialogCancellation && e.KeyCode == Keys.Escape)
|
|
{
|
|
CloseForm();
|
|
e.Handled = true;
|
|
}
|
|
base.OnKeyDown(e);
|
|
}
|
|
|
|
protected override void OnLoad(EventArgs e)
|
|
{
|
|
base.OnLoad(e);
|
|
|
|
taskDialog.InitializeButtonState();
|
|
taskDialog.ProgressBar.Initialize();
|
|
taskDialog.OnLoad();
|
|
}
|
|
|
|
protected override void WndProc(ref Message m)
|
|
{
|
|
if (Enum.IsDefined(typeof(TaskDialogMessage), (uint)m.Msg))
|
|
{
|
|
switch ((TaskDialogMessage)m.Msg)
|
|
{
|
|
case TaskDialogMessage.TDM_CLICK_BUTTON:
|
|
PerformButtonClick(m.WParam.ToInt32());
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_SET_MARQUEE_PROGRESS_BAR:
|
|
SetMarqueeProgressBar(m.WParam.ToInt32() == 1);
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_SET_PROGRESS_BAR_STATE:
|
|
SetProgressBarState((ProgressBarState)m.WParam.ToInt32());
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_SET_PROGRESS_BAR_RANGE:
|
|
var ab = unchecked(IntPtr.Size == 8 ? (uint)m.LParam.ToInt64() : (uint)m.LParam.ToInt32());
|
|
int a = unchecked((short)ab);
|
|
int b = unchecked((short)(ab >> 16));
|
|
SetProgressBarRange(a, b);
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_SET_PROGRESS_BAR_POS:
|
|
SetProgressBarValue(m.WParam.ToInt32());
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_SET_PROGRESS_BAR_MARQUEE:
|
|
SetProgressBarValue(m.LParam.ToInt32());
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_SET_ELEMENT_TEXT:
|
|
case TaskDialogMessage.TDM_UPDATE_ELEMENT_TEXT:
|
|
SetElementText((TaskDialogElement)m.WParam.ToInt32(), Marshal.PtrToStringAuto(m.LParam));
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_CLICK_RADIO_BUTTON:
|
|
PerformRadioButtonClick(m.WParam.ToInt32());
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_ENABLE_BUTTON:
|
|
EnableButton(m.WParam.ToInt32(), m.LParam.ToInt32() == 1);
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_ENABLE_RADIO_BUTTON:
|
|
EnableRadioButton(m.WParam.ToInt32(), m.LParam.ToInt32() == 1);
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_CLICK_VERIFICATION:
|
|
PerformVerificationClick(m.WParam.ToInt32() == 1, m.LParam.ToInt32() == 1);
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE:
|
|
SetButtonElevationRequiredState(m.WParam.ToInt32(), m.LParam.ToInt32() == 1);
|
|
break;
|
|
|
|
case TaskDialogMessage.TDM_UPDATE_ICON:
|
|
if (Enum.IsDefined(typeof(TaskDialogIcon), m.LParam.ToInt32()))
|
|
SetCommonIcon((TaskDialogIconElement)m.WParam.ToInt32(), (TaskDialogIcon)m.LParam.ToInt32());
|
|
else
|
|
SetIcon((TaskDialogIconElement)m.WParam.ToInt32(), Icon.FromHandle(m.LParam));
|
|
break;
|
|
}
|
|
}
|
|
|
|
base.WndProc(ref m);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a standard button with a common event handler to close the
|
|
/// the form and return the button's Id.
|
|
/// </summary>
|
|
/// <param name="tag">The button's Id.</param>
|
|
/// <param name="text">The button's name.</param>
|
|
/// <returns></returns>
|
|
private Button BuildControlButton(int tag, string text)
|
|
{
|
|
var button = new Button { Tag = tag, Text = text, Margin = new Padding(7, 0, 0, 7) };
|
|
button.Width -= 5;
|
|
button.Click += button_Click;
|
|
|
|
taskDialogButtons.Add(tag, button);
|
|
|
|
return button;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a standard link label and will convert any anchor links to
|
|
/// a proper link.
|
|
/// </summary>
|
|
/// <param name="margin">The margin of the link label.</param>
|
|
/// <param name="text">The text of the link label.</param>
|
|
/// <param name="name">The name assigned to the label.</param>
|
|
/// <returns>A <see cref="LinkLabel"/> matching the parameters.</returns>
|
|
private LinkLabel BuildControlLinkLabel(Padding margin, string text, string name)
|
|
{
|
|
var linkLabel = new LinkLabel
|
|
{
|
|
AutoSize = true,
|
|
Font = new Font(Font.FontFamily, 9),
|
|
LinkArea = new LinkArea(),
|
|
Margin = margin,
|
|
Name = name,
|
|
Text = text
|
|
};
|
|
linkLabel.LinkClicked += linkLabel_LinkClicked;
|
|
|
|
if (taskDialog.EnableHyperlinks)
|
|
{
|
|
linkLabel = ParseLinkLabel(linkLabel);
|
|
}
|
|
|
|
return linkLabel;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Main entry method to build the form.
|
|
/// </summary>
|
|
private void BuildForm()
|
|
{
|
|
ControlBox = taskDialog.AllowDialogCancellation;
|
|
if ((MinimizeBox = taskDialog.CanBeMinimized) == true)
|
|
{
|
|
// If can be minimized, ControlBox must be enabled.
|
|
ControlBox = true;
|
|
ShowInTaskbar = true;
|
|
|
|
// TODO: Form icon will be the TaskDialog.MainIcon. Problem is .Net framework does not provide a way to generate an icon.
|
|
}
|
|
StartPosition = taskDialog.PositionRelativeToWindow ? FormStartPosition.CenterParent : FormStartPosition.CenterScreen;
|
|
Text = string.IsNullOrEmpty(taskDialog.WindowTitle) ? "" : taskDialog.WindowTitle;
|
|
|
|
BuildFormMainArea();
|
|
BuildFormFooterArea();
|
|
// Build the sub area last because of the possibility of having the expanded information
|
|
// in the footer. Then building the "expand/collapse" button will be accurate.
|
|
BuildFormSubArea();
|
|
|
|
SetFormHeight();
|
|
}
|
|
|
|
private void BuildFormFooterArea()
|
|
{
|
|
if (!string.IsNullOrEmpty(taskDialog.Footer))
|
|
{
|
|
if (taskDialog.CustomFooterIcon != null)
|
|
SetFooterIcon(taskDialog.CustomFooterIcon);
|
|
else
|
|
SetFooterIcon(taskDialog.FooterIcon);
|
|
|
|
flowLayoutPanelFooterAreaText.Controls.Add(BuildControlLinkLabel(new Padding(0, 0, 0, 11), taskDialog.Footer, "Footer"));
|
|
}
|
|
else
|
|
{
|
|
tableLayoutPanelFooterArea.AutoSize = false;
|
|
tableLayoutPanelFooterArea.Height = 0;
|
|
tableLayoutPanelFooterArea.Visible = false;
|
|
|
|
tableLayoutPanel2.Height = 0;
|
|
tableLayoutPanel2.Visible = false;
|
|
}
|
|
|
|
if (taskDialog.ExpandFooterArea && !string.IsNullOrEmpty(taskDialog.ExpandedInformation))
|
|
{
|
|
linkLabelExpandedInformation = BuildControlLinkLabel(new Padding(0), taskDialog.ExpandedInformation, "ExpandedInformation");
|
|
|
|
flowLayoutPanelFooterExpandedInformationText.Controls.Add(linkLabelExpandedInformation);
|
|
|
|
if (!taskDialog.ExpandedByDefault)
|
|
{
|
|
ToggleExpandedInformationState();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
flowLayoutPanelFooterExpandedInformationText.AutoSize = false;
|
|
flowLayoutPanelFooterExpandedInformationText.Height = 0;
|
|
tableLayoutPanelFooterExpandedInformationArea.Visible = false;
|
|
|
|
tableLayoutPanel3.Height = tableLayoutPanel4.Height = 0;
|
|
tableLayoutPanel3.Visible = tableLayoutPanel4.Visible = false;
|
|
}
|
|
}
|
|
|
|
private void BuildFormMainArea()
|
|
{
|
|
var colorBg = Color.White;
|
|
var colorFg = Color.FromArgb(0, 0, 51, 153);
|
|
|
|
// Main icon
|
|
if (taskDialog.CustomMainIcon != null)
|
|
SetMainIcon(taskDialog.CustomMainIcon);
|
|
else
|
|
{
|
|
SetMainIcon(taskDialog.MainIcon);
|
|
switch (taskDialog.MainIcon)
|
|
{
|
|
case TaskDialogIcon.SecurityError:
|
|
colorFg = Color.White;
|
|
colorBg = Color.FromArgb(199, 1, 0);
|
|
break;
|
|
case TaskDialogIcon.SecurityWarning:
|
|
colorFg = Color.Black;
|
|
colorBg = Color.FromArgb(248, 191, 35);
|
|
break;
|
|
case TaskDialogIcon.SecuritySuccess:
|
|
colorFg = Color.White;
|
|
colorBg = Color.FromArgb(38, 134, 41);
|
|
break;
|
|
case TaskDialogIcon.ShieldBlue:
|
|
colorFg = Color.White;
|
|
colorBg = Color.FromArgb(16, 100, 131);
|
|
break;
|
|
case TaskDialogIcon.ShieldGray:
|
|
colorFg = Color.White;
|
|
colorBg = Color.FromArgb(160, 147, 138);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Main instruction
|
|
if (!string.IsNullOrEmpty(taskDialog.MainInstruction))
|
|
{
|
|
var label = new Label
|
|
{
|
|
AutoSize = true,
|
|
Name = "MainInstruction",
|
|
Text = taskDialog.MainInstruction,
|
|
Font = new Font(Font.FontFamily, 12),
|
|
ForeColor = colorFg,
|
|
Margin = new Padding(0, 0, 0, hPadding)
|
|
};
|
|
|
|
flowLayoutPanelMainAreaControls.Controls.Add(label);
|
|
tableLayoutPanelMainArea.BackColor = colorBg;
|
|
}
|
|
|
|
// Content
|
|
if (!string.IsNullOrEmpty(taskDialog.Content))
|
|
{
|
|
flowLayoutPanelMainAreaControls.Controls.Add(BuildControlLinkLabel(new Padding(0, 0, 0, hPadding), taskDialog.Content, "Content"));
|
|
}
|
|
|
|
// Expanded info
|
|
if (!string.IsNullOrEmpty(taskDialog.ExpandedInformation) && !taskDialog.ExpandFooterArea)
|
|
{
|
|
linkLabelExpandedInformation = BuildControlLinkLabel(new Padding(0, 0, 0, hPadding), taskDialog.ExpandedInformation, "ExpandedInformation");
|
|
|
|
flowLayoutPanelMainAreaControls.Controls.Add(linkLabelExpandedInformation);
|
|
|
|
if (!taskDialog.ExpandedByDefault)
|
|
{
|
|
ToggleExpandedInformationState();
|
|
}
|
|
}
|
|
|
|
// ProgressBar
|
|
if (taskDialog.ShowProgressBar || taskDialog.ShowMarqueeProgressBar)
|
|
{
|
|
progressBar = new ProgressBar
|
|
{
|
|
Margin = new Padding(2, 0, 0, hPadding),
|
|
Size = new Size(flowLayoutPanelMainAreaControls.Width - 6, 15)
|
|
};
|
|
if (taskDialog.ShowMarqueeProgressBar)
|
|
progressBar.Style = ProgressBarStyle.Marquee;
|
|
|
|
flowLayoutPanelMainAreaControls.Controls.Add(progressBar);
|
|
}
|
|
|
|
// Radio buttons
|
|
for (var i = 0; i < taskDialog.RadioButtons.Count; i++)
|
|
{
|
|
var radioButton = new RadioButton
|
|
{
|
|
Text = taskDialog.RadioButtons[i].ButtonText,
|
|
Tag = taskDialog.RadioButtons[i].ButtonId,
|
|
AutoSize = true,
|
|
Margin = new Padding(14, 0, 0, i == (taskDialog.RadioButtons.Count - 1) ? hPadding : 3)
|
|
};
|
|
radioButton.Click += radioButton_Click;
|
|
// Select the first radio button by default.
|
|
if ((i == 0) || (taskDialog.DefaultRadioButton == taskDialog.RadioButtons[i].ButtonId))
|
|
defaultRadioButton = radioButton;
|
|
|
|
flowLayoutPanelMainAreaControls.Controls.Add(radioButton);
|
|
}
|
|
|
|
// Command links
|
|
if (taskDialog.UseCommandLinks)
|
|
{
|
|
foreach (var t in taskDialog.Buttons)
|
|
{
|
|
var cmdLink = new CommandLink
|
|
{
|
|
Tag = t.ButtonId,
|
|
Text = t.ButtonText,
|
|
Margin = new Padding(1, 0, 0, 1)
|
|
};
|
|
cmdLink.Size = cmdLink.GetPreferredSize(new Size(flowLayoutPanelMainAreaControls.Width - 10, 0));
|
|
cmdLink.Click += button_Click;
|
|
|
|
taskDialogButtons.Add(t.ButtonId, cmdLink);
|
|
|
|
flowLayoutPanelMainAreaControls.Controls.Add(cmdLink);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void BuildFormSubArea()
|
|
{
|
|
// --------------- Left side of the sub control area. ---------------
|
|
// Check if there is any expanded information first.
|
|
if (!string.IsNullOrEmpty(taskDialog.ExpandedInformation))
|
|
{
|
|
expandedInfoButton = new EmulateExpInfoButton(isExpanded, taskDialog.ExpandedControlText,
|
|
taskDialog.CollapsedControlText) {Margin = Padding.Empty};
|
|
expandedInfoButton.Click += expandedInfoButton_Click;
|
|
|
|
flowLayoutPanelSubAreaControls.Controls.Add(expandedInfoButton);
|
|
// Smallest element in this area.
|
|
tableLayoutPanelSubArea.MinimumSize = new Size(0, 33);
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(taskDialog.VerificationText))
|
|
{
|
|
var checkBox = new CheckBox
|
|
{
|
|
Checked = taskDialog.VerificationFlagChecked,
|
|
Margin = new Padding(3, 3, 0, 0),
|
|
MaximumSize = new Size(165, 0),
|
|
Name = "VerificationText",
|
|
Text = taskDialog.VerificationText,
|
|
Width = 165
|
|
};
|
|
|
|
checkBox.Click += verificationCheckBox_Click;
|
|
|
|
// AdjustControls doesn't take in account the checkbox, so need
|
|
// to work around it.
|
|
var size = AdjustControls.GetBestSize(checkBox, checkBox.Text, new Rectangle(0, 0, checkBox.Width - 52, checkBox.Height));
|
|
checkBox.Height = size.Height + 6;
|
|
|
|
flowLayoutPanelSubAreaControls.Controls.Add(checkBox);
|
|
}
|
|
|
|
// --------------- Right side of the sub control area. ---------------
|
|
var commBtns = taskDialog.CommonButtons;
|
|
|
|
// If there is no button, by default there will be an "Okay" button.
|
|
if (commBtns == TaskDialogCommonButtons.None && taskDialog.Buttons.Count == 0)
|
|
commBtns = TaskDialogCommonButtons.Ok;
|
|
|
|
var requiredTotalButtonsWidth = 0;
|
|
|
|
var commonButtons = (TaskDialogCommonButtons[])Enum.GetValues(typeof(TaskDialogCommonButtons));
|
|
|
|
// Iterate through all the common buttons. Get by reverse order
|
|
// as the layout direction is right to left.
|
|
for (var i = commonButtons.Length - 1; i >= 0; i--)
|
|
{
|
|
// There is no "None" button.
|
|
if (!commonButtons[i].Equals(TaskDialogCommonButtons.None))
|
|
{
|
|
// Now to check which button is needed.
|
|
if ((commBtns & commonButtons[i]).Equals(commonButtons[i]))
|
|
{
|
|
// TaskDialogCommonButtons enums is not the same as DialogResult enums. Need
|
|
// to use another way of getting the correct DialogResult value.
|
|
Button button;
|
|
|
|
// DialogResult does not contain a "Close" enum, return value by TaskDialog is int 8.
|
|
if (commonButtons[i].Equals(TaskDialogCommonButtons.Close))
|
|
{
|
|
button = BuildControlButton(8, TaskDialogCommonButtons.Close.ToString());
|
|
}
|
|
// No "Ok" button. Is it a typo for TaskDialogCommonButtons in TaskDialog.cs?
|
|
else if (commonButtons[i].Equals(TaskDialogCommonButtons.Ok))
|
|
{
|
|
button = BuildControlButton((int)DialogResult.OK, DialogResult.OK.ToString());
|
|
}
|
|
else
|
|
{
|
|
var result = (DialogResult)Enum.Parse(typeof(DialogResult), commonButtons[i].ToString());
|
|
button = BuildControlButton((int)result, result.ToString());
|
|
}
|
|
|
|
button.TabIndex = i + taskDialog.Buttons.Count;
|
|
|
|
flowLayoutPanelSubAreaButtons.Controls.Add(button);
|
|
|
|
requiredTotalButtonsWidth += button.Width + button.Margin.Left + button.Margin.Right;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Custom buttons. Get by reverse order as the layout direction
|
|
// is right to left.
|
|
if (!taskDialog.UseCommandLinks)
|
|
{
|
|
for (var i = taskDialog.Buttons.Count - 1; i >= 0; i--)
|
|
{
|
|
var button = BuildControlButton(taskDialog.Buttons[i].ButtonId, taskDialog.Buttons[i].ButtonText);
|
|
flowLayoutPanelSubAreaButtons.Controls.Add(button);
|
|
|
|
button.TabIndex = i;
|
|
|
|
requiredTotalButtonsWidth += button.Width + button.Margin.Left + button.Margin.Right;
|
|
}
|
|
}
|
|
|
|
// Check if there is anything in the sub area.
|
|
if ((requiredTotalButtonsWidth == 0) && (string.IsNullOrEmpty(taskDialog.ExpandedInformation)) && (string.IsNullOrEmpty(taskDialog.VerificationText)))
|
|
{
|
|
tableLayoutPanel1.Visible = false;
|
|
tableLayoutPanel1.Height = 0;
|
|
tableLayoutPanelSubArea.Visible = false;
|
|
}
|
|
else
|
|
{
|
|
// Padding on the right.
|
|
requiredTotalButtonsWidth += 15;
|
|
|
|
if (requiredTotalButtonsWidth > flowLayoutPanelSubAreaButtons.Width)
|
|
{
|
|
Width += requiredTotalButtonsWidth - flowLayoutPanelSubAreaButtons.Width;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void button_Click(object? sender, EventArgs e)
|
|
{
|
|
var id = (int)((Button)sender).Tag;
|
|
if (taskDialog.OnButtonClicked(id))
|
|
return;
|
|
|
|
TaskDialogResult = id;
|
|
CloseForm();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Closes the form and populate the necessary return results.
|
|
/// </summary>
|
|
private void CloseForm()
|
|
{
|
|
if (taskDialog.RadioButtons.Count > 0)
|
|
{
|
|
// Check all the radio buttons.
|
|
foreach (Control control in flowLayoutPanelMainAreaControls.Controls)
|
|
{
|
|
var button = control as RadioButton;
|
|
if (button == null) continue;
|
|
var radioButton = button;
|
|
if (!radioButton.Checked) continue;
|
|
TaskDialogRadioButtonResult = (int)radioButton.Tag;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(taskDialog.VerificationText))
|
|
{
|
|
foreach (Control control in flowLayoutPanelSubAreaControls.Controls)
|
|
{
|
|
var box = control as CheckBox;
|
|
if (box == null) continue;
|
|
TaskDialogVerificationFlagChecked = box.Checked;
|
|
break;
|
|
}
|
|
}
|
|
|
|
timer.Stop();
|
|
|
|
Close();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Detect user pressing "ctrl + c".
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void EmulateTaskDialog_KeyDown(object? sender, KeyEventArgs e)
|
|
{
|
|
var notWanted = Keys.Alt | Keys.Shift;
|
|
|
|
if ((e.Modifiers & notWanted) == 0)
|
|
{
|
|
if ((e.Modifiers & Keys.Control) == Keys.Control)
|
|
{
|
|
if (e.KeyCode.Equals(Keys.C))
|
|
{
|
|
Clipboard.SetText(ToString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void expandedInfoButton_Click(object? sender, EventArgs e)
|
|
{
|
|
ToggleExpandedInformationState();
|
|
|
|
expandedInfoButton.ToogleState();
|
|
|
|
SetFormHeight();
|
|
|
|
taskDialog.OnExpanded(isExpanded);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Required method for Designer support - do not modify
|
|
/// the contents of this method with the code editor.
|
|
/// </summary>
|
|
private void InitializeComponent()
|
|
{
|
|
components = new System.ComponentModel.Container();
|
|
tableLayoutPanelMainArea = new TableLayoutPanel();
|
|
flowLayoutPanelMainAreaControls = new FlowLayoutPanel();
|
|
pictureBoxMainAreaIcon = new PictureBox();
|
|
tableLayoutPanel1 = new Panel();
|
|
tableLayoutPanelSubArea = new TableLayoutPanel();
|
|
flowLayoutPanelSubAreaButtons = new FlowLayoutPanel();
|
|
flowLayoutPanelSubAreaControls = new FlowLayoutPanel();
|
|
tableLayoutPanelFooterArea = new TableLayoutPanel();
|
|
pictureBoxFooterAreaIcon = new PictureBox();
|
|
flowLayoutPanelFooterAreaText = new FlowLayoutPanel();
|
|
tableLayoutPanel2 = new Panel();
|
|
tableLayoutPanel3 = new Panel();
|
|
tableLayoutPanel4 = new Panel();
|
|
tableLayoutPanelFooterExpandedInformationArea = new TableLayoutPanel();
|
|
flowLayoutPanelFooterExpandedInformationText = new FlowLayoutPanel();
|
|
timer = new Timer(components);
|
|
tableLayoutPanelMainArea.SuspendLayout();
|
|
((System.ComponentModel.ISupportInitialize)(pictureBoxMainAreaIcon)).BeginInit();
|
|
tableLayoutPanelSubArea.SuspendLayout();
|
|
tableLayoutPanelFooterArea.SuspendLayout();
|
|
((System.ComponentModel.ISupportInitialize)(pictureBoxFooterAreaIcon)).BeginInit();
|
|
tableLayoutPanelFooterExpandedInformationArea.SuspendLayout();
|
|
SuspendLayout();
|
|
//
|
|
// tableLayoutPanelMainArea
|
|
//
|
|
tableLayoutPanelMainArea.AutoSize = true;
|
|
tableLayoutPanelMainArea.BackColor = Color.White;
|
|
tableLayoutPanelMainArea.ColumnCount = 2;
|
|
tableLayoutPanelMainArea.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 32F));
|
|
tableLayoutPanelMainArea.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
|
tableLayoutPanelMainArea.Controls.Add(flowLayoutPanelMainAreaControls, 1, 0);
|
|
tableLayoutPanelMainArea.Controls.Add(pictureBoxMainAreaIcon, 0, 0);
|
|
tableLayoutPanelMainArea.Dock = DockStyle.Top;
|
|
tableLayoutPanelMainArea.Location = new Point(0, 0);
|
|
tableLayoutPanelMainArea.Margin = new Padding(0);
|
|
tableLayoutPanelMainArea.MinimumSize = new Size(0, 52);
|
|
tableLayoutPanelMainArea.Name = "tableLayoutPanelMainArea";
|
|
tableLayoutPanelMainArea.Padding = new Padding(10);
|
|
tableLayoutPanelMainArea.RowCount = 1;
|
|
tableLayoutPanelMainArea.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
|
tableLayoutPanelMainArea.Size = new Size(460, 52);
|
|
tableLayoutPanelMainArea.TabIndex = 0;
|
|
//
|
|
// flowLayoutPanelMainAreaControls
|
|
//
|
|
flowLayoutPanelMainAreaControls.AutoSize = true;
|
|
flowLayoutPanelMainAreaControls.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
|
flowLayoutPanelMainAreaControls.Dock = DockStyle.Fill;
|
|
flowLayoutPanelMainAreaControls.FlowDirection = FlowDirection.TopDown;
|
|
flowLayoutPanelMainAreaControls.Location = new Point(42, 10);
|
|
flowLayoutPanelMainAreaControls.Margin = new Padding(0);
|
|
flowLayoutPanelMainAreaControls.Name = "flowLayoutPanelMainAreaControls";
|
|
flowLayoutPanelMainAreaControls.Size = new Size(408, 32);
|
|
flowLayoutPanelMainAreaControls.TabIndex = 0;
|
|
//
|
|
// pictureBoxMainAreaIcon
|
|
//
|
|
pictureBoxMainAreaIcon.Location = new Point(10, 10);
|
|
pictureBoxMainAreaIcon.Margin = new Padding(0);
|
|
pictureBoxMainAreaIcon.Name = "pictureBoxMainAreaIcon";
|
|
pictureBoxMainAreaIcon.Size = new Size(32, 32);
|
|
pictureBoxMainAreaIcon.TabIndex = 1;
|
|
pictureBoxMainAreaIcon.TabStop = false;
|
|
//
|
|
// tableLayoutPanel1
|
|
//
|
|
tableLayoutPanel1.BackColor = SystemColors.ControlLight;
|
|
tableLayoutPanel1.Dock = DockStyle.Top;
|
|
tableLayoutPanel1.Location = new Point(0, 52);
|
|
tableLayoutPanel1.Margin = new Padding(0);
|
|
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
|
tableLayoutPanel1.Size = new Size(460, 1);
|
|
tableLayoutPanel1.TabIndex = 1;
|
|
//
|
|
// tableLayoutPanelSubArea
|
|
//
|
|
tableLayoutPanelSubArea.AutoSize = true;
|
|
tableLayoutPanelSubArea.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
|
tableLayoutPanelSubArea.BackColor = SystemColors.ButtonFace;
|
|
tableLayoutPanelSubArea.ColumnCount = 2;
|
|
tableLayoutPanelSubArea.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 175F));
|
|
tableLayoutPanelSubArea.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
|
tableLayoutPanelSubArea.Controls.Add(flowLayoutPanelSubAreaButtons, 1, 0);
|
|
tableLayoutPanelSubArea.Controls.Add(flowLayoutPanelSubAreaControls, 0, 0);
|
|
tableLayoutPanelSubArea.Dock = DockStyle.Top;
|
|
tableLayoutPanelSubArea.Location = new Point(0, 53);
|
|
tableLayoutPanelSubArea.Margin = new Padding(0);
|
|
tableLayoutPanelSubArea.MinimumSize = new Size(0, 33);
|
|
tableLayoutPanelSubArea.Name = "tableLayoutPanelSubArea";
|
|
tableLayoutPanelSubArea.Padding = new Padding(10, 9, 10, 9);
|
|
tableLayoutPanelSubArea.RowCount = 1;
|
|
tableLayoutPanelSubArea.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
|
tableLayoutPanelSubArea.Size = new Size(460, 33);
|
|
tableLayoutPanelSubArea.TabIndex = 1;
|
|
//
|
|
// flowLayoutPanelSubAreaButtons
|
|
//
|
|
flowLayoutPanelSubAreaButtons.AutoSize = true;
|
|
flowLayoutPanelSubAreaButtons.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
|
flowLayoutPanelSubAreaButtons.Dock = DockStyle.Fill;
|
|
flowLayoutPanelSubAreaButtons.FlowDirection = FlowDirection.RightToLeft;
|
|
flowLayoutPanelSubAreaButtons.Location = new Point(185, 9);
|
|
flowLayoutPanelSubAreaButtons.Margin = new Padding(0);
|
|
flowLayoutPanelSubAreaButtons.Name = "flowLayoutPanelSubAreaButtons";
|
|
flowLayoutPanelSubAreaButtons.Size = new Size(265, 15);
|
|
flowLayoutPanelSubAreaButtons.TabIndex = 1;
|
|
flowLayoutPanelSubAreaButtons.WrapContents = false;
|
|
//
|
|
// flowLayoutPanelSubAreaControls
|
|
//
|
|
flowLayoutPanelSubAreaControls.AutoSize = true;
|
|
flowLayoutPanelSubAreaControls.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
|
flowLayoutPanelSubAreaControls.Dock = DockStyle.Fill;
|
|
flowLayoutPanelSubAreaControls.FlowDirection = FlowDirection.TopDown;
|
|
flowLayoutPanelSubAreaControls.Location = new Point(10, 9);
|
|
flowLayoutPanelSubAreaControls.Margin = new Padding(0);
|
|
flowLayoutPanelSubAreaControls.Name = "flowLayoutPanelSubAreaControls";
|
|
flowLayoutPanelSubAreaControls.Size = new Size(175, 15);
|
|
flowLayoutPanelSubAreaControls.TabIndex = 0;
|
|
//
|
|
// tableLayoutPanelFooterArea
|
|
//
|
|
tableLayoutPanelFooterArea.AutoSize = true;
|
|
tableLayoutPanelFooterArea.BackColor = SystemColors.Control;
|
|
tableLayoutPanelFooterArea.ColumnCount = 2;
|
|
tableLayoutPanelFooterArea.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 24F));
|
|
tableLayoutPanelFooterArea.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
|
tableLayoutPanelFooterArea.Controls.Add(pictureBoxFooterAreaIcon, 0, 0);
|
|
tableLayoutPanelFooterArea.Controls.Add(flowLayoutPanelFooterAreaText, 1, 0);
|
|
tableLayoutPanelFooterArea.Dock = DockStyle.Top;
|
|
tableLayoutPanelFooterArea.Location = new Point(0, 87);
|
|
tableLayoutPanelFooterArea.Margin = new Padding(0);
|
|
tableLayoutPanelFooterArea.Name = "tableLayoutPanelFooterArea";
|
|
tableLayoutPanelFooterArea.Padding = new Padding(10, 10, 10, 0);
|
|
tableLayoutPanelFooterArea.RowCount = 1;
|
|
tableLayoutPanelFooterArea.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
|
tableLayoutPanelFooterArea.Size = new Size(460, 26);
|
|
tableLayoutPanelFooterArea.TabIndex = 2;
|
|
//
|
|
// pictureBoxFooterAreaIcon
|
|
//
|
|
pictureBoxFooterAreaIcon.Location = new Point(10, 10);
|
|
pictureBoxFooterAreaIcon.Margin = new Padding(0);
|
|
pictureBoxFooterAreaIcon.Name = "pictureBoxFooterAreaIcon";
|
|
pictureBoxFooterAreaIcon.Size = new Size(16, 16);
|
|
pictureBoxFooterAreaIcon.TabIndex = 0;
|
|
pictureBoxFooterAreaIcon.TabStop = false;
|
|
//
|
|
// flowLayoutPanelFooterAreaText
|
|
//
|
|
flowLayoutPanelFooterAreaText.AutoSize = true;
|
|
flowLayoutPanelFooterAreaText.Dock = DockStyle.Fill;
|
|
flowLayoutPanelFooterAreaText.FlowDirection = FlowDirection.TopDown;
|
|
flowLayoutPanelFooterAreaText.Location = new Point(34, 10);
|
|
flowLayoutPanelFooterAreaText.Margin = new Padding(0);
|
|
flowLayoutPanelFooterAreaText.Name = "flowLayoutPanelFooterAreaText";
|
|
flowLayoutPanelFooterAreaText.Size = new Size(416, 16);
|
|
flowLayoutPanelFooterAreaText.TabIndex = 1;
|
|
//
|
|
// tableLayoutPanel2
|
|
//
|
|
tableLayoutPanel2.BackColor = SystemColors.ControlLight;
|
|
tableLayoutPanel2.Dock = DockStyle.Top;
|
|
tableLayoutPanel2.Location = new Point(0, 86);
|
|
tableLayoutPanel2.Margin = new Padding(0);
|
|
tableLayoutPanel2.Name = "tableLayoutPanel2";
|
|
tableLayoutPanel2.Size = new Size(460, 1);
|
|
tableLayoutPanel2.TabIndex = 4;
|
|
//
|
|
// tableLayoutPanel3
|
|
//
|
|
tableLayoutPanel3.BackColor = SystemColors.ControlLight;
|
|
tableLayoutPanel3.Dock = DockStyle.Top;
|
|
tableLayoutPanel3.Location = new Point(0, 113);
|
|
tableLayoutPanel3.Margin = new Padding(0);
|
|
tableLayoutPanel3.Name = "tableLayoutPanel3";
|
|
tableLayoutPanel3.Size = new Size(460, 1);
|
|
tableLayoutPanel3.TabIndex = 7;
|
|
//
|
|
// tableLayoutPanel4
|
|
//
|
|
tableLayoutPanel4.BackColor = SystemColors.ControlLightLight;
|
|
tableLayoutPanel4.Dock = DockStyle.Top;
|
|
tableLayoutPanel4.Location = new Point(0, 114);
|
|
tableLayoutPanel4.Margin = new Padding(0);
|
|
tableLayoutPanel4.Name = "tableLayoutPanel4";
|
|
tableLayoutPanel4.Size = new Size(460, 1);
|
|
tableLayoutPanel4.TabIndex = 8;
|
|
//
|
|
// tableLayoutPanelFooterExpandedInformationArea
|
|
//
|
|
tableLayoutPanelFooterExpandedInformationArea.AutoSize = true;
|
|
tableLayoutPanelFooterExpandedInformationArea.BackColor = SystemColors.ButtonFace;
|
|
tableLayoutPanelFooterExpandedInformationArea.ColumnCount = 1;
|
|
tableLayoutPanelFooterExpandedInformationArea.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
|
tableLayoutPanelFooterExpandedInformationArea.Controls.Add(flowLayoutPanelFooterExpandedInformationText, 0, 0);
|
|
tableLayoutPanelFooterExpandedInformationArea.Dock = DockStyle.Top;
|
|
tableLayoutPanelFooterExpandedInformationArea.Location = new Point(0, 115);
|
|
tableLayoutPanelFooterExpandedInformationArea.Margin = new Padding(0);
|
|
tableLayoutPanelFooterExpandedInformationArea.Name = "tableLayoutPanelFooterExpandedInformationArea";
|
|
tableLayoutPanelFooterExpandedInformationArea.Padding = new Padding(10, 10, 10, 0);
|
|
tableLayoutPanelFooterExpandedInformationArea.RowCount = 1;
|
|
tableLayoutPanelFooterExpandedInformationArea.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
|
tableLayoutPanelFooterExpandedInformationArea.Size = new Size(460, 10);
|
|
tableLayoutPanelFooterExpandedInformationArea.TabIndex = 3;
|
|
//
|
|
// flowLayoutPanelFooterExpandedInformationText
|
|
//
|
|
flowLayoutPanelFooterExpandedInformationText.AutoSize = true;
|
|
flowLayoutPanelFooterExpandedInformationText.Dock = DockStyle.Fill;
|
|
flowLayoutPanelFooterExpandedInformationText.FlowDirection = FlowDirection.TopDown;
|
|
flowLayoutPanelFooterExpandedInformationText.Location = new Point(10, 10);
|
|
flowLayoutPanelFooterExpandedInformationText.Margin = new Padding(0);
|
|
flowLayoutPanelFooterExpandedInformationText.Name = "flowLayoutPanelFooterExpandedInformationText";
|
|
flowLayoutPanelFooterExpandedInformationText.Size = new Size(440, 1);
|
|
flowLayoutPanelFooterExpandedInformationText.TabIndex = 0;
|
|
//
|
|
// timer
|
|
//
|
|
timer.Tick += timer_Tick;
|
|
//
|
|
// EmulateTaskDialog
|
|
//
|
|
AutoScaleDimensions = new SizeF(7F, 15F);
|
|
AutoScaleMode = AutoScaleMode.Font;
|
|
BackColor = SystemColors.Control;
|
|
ClientSize = new Size(360, 200);
|
|
Controls.Add(tableLayoutPanelFooterExpandedInformationArea);
|
|
Controls.Add(tableLayoutPanel4);
|
|
Controls.Add(tableLayoutPanel3);
|
|
Controls.Add(tableLayoutPanelFooterArea);
|
|
Controls.Add(tableLayoutPanel2);
|
|
Controls.Add(tableLayoutPanelSubArea);
|
|
Controls.Add(tableLayoutPanel1);
|
|
Controls.Add(tableLayoutPanelMainArea);
|
|
Font = new Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point, 0);
|
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
|
KeyPreview = true;
|
|
MaximizeBox = false;
|
|
Name = "EmulateTaskDialog";
|
|
ShowInTaskbar = false;
|
|
Text = @"EmulateTaskDialog";
|
|
KeyDown += EmulateTaskDialog_KeyDown;
|
|
tableLayoutPanelMainArea.ResumeLayout(false);
|
|
tableLayoutPanelMainArea.PerformLayout();
|
|
((System.ComponentModel.ISupportInitialize)(pictureBoxMainAreaIcon)).EndInit();
|
|
tableLayoutPanelSubArea.ResumeLayout(false);
|
|
tableLayoutPanelSubArea.PerformLayout();
|
|
tableLayoutPanelFooterArea.ResumeLayout(false);
|
|
tableLayoutPanelFooterArea.PerformLayout();
|
|
((System.ComponentModel.ISupportInitialize)(pictureBoxFooterAreaIcon)).EndInit();
|
|
tableLayoutPanelFooterExpandedInformationArea.ResumeLayout(false);
|
|
tableLayoutPanelFooterExpandedInformationArea.PerformLayout();
|
|
ResumeLayout(false);
|
|
PerformLayout();
|
|
}
|
|
|
|
private void linkLabel_LinkClicked(object? sender, LinkLabelLinkClickedEventArgs e)
|
|
{
|
|
taskDialog.OnLinkClicked((string)e.Link.LinkData);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses a LinkLabel text and extract out all the anchor (a) tags.
|
|
/// Then it will parse all the anchor tags and create the relevant
|
|
/// links in the text.
|
|
/// </summary>
|
|
/// <param name="linkLabel"></param>
|
|
/// <returns></returns>
|
|
private LinkLabel ParseLinkLabel(LinkLabel linkLabel)
|
|
{
|
|
// Set up the text to parse.
|
|
var text = linkLabel.Text;
|
|
|
|
// Set up the regex for finding the link urls.
|
|
var hrefPattern = new StringBuilder();
|
|
// Start anchor tag and anything that comes before "href" tag.
|
|
hrefPattern.Append("<a[^>]+");
|
|
hrefPattern.Append("href\\s*=\\s*"); // Start href property.
|
|
// Three possibilities for "href":
|
|
// (1) enclosed in double quotes.
|
|
// (2) enclosed in single quotes.
|
|
// (3) enclosed in spaces.
|
|
hrefPattern.Append("(?:\"(?<href>[^\"]*)\"|'(?<href>[^']*)'|(?<href>[^\"'>\\s]+))");
|
|
// Grab the inner html too.
|
|
hrefPattern.Append("[^>]*>(?<a>.*?)</a>"); // End of anchor tag.
|
|
var hrefRegex = new Regex(hrefPattern.ToString(), RegexOptions.IgnoreCase);
|
|
|
|
// Look for matches.
|
|
var hrefCheck = hrefRegex.Match(text);
|
|
|
|
while (hrefCheck.Success)
|
|
{
|
|
var href = hrefCheck.Groups["href"].Value;
|
|
var innerText = hrefCheck.Groups["a"].Value;
|
|
|
|
// Get the starting index of the anchor tag.
|
|
var index = linkLabel.Text.IndexOf(hrefCheck.Value, StringComparison.Ordinal);
|
|
// Replace it with the inner text, create a link and store the
|
|
// link.
|
|
linkLabel.Text = linkLabel.Text.Replace(hrefCheck.Value, innerText);
|
|
linkLabel.Links.Add(index, innerText.Length, href);
|
|
|
|
hrefCheck = hrefCheck.NextMatch();
|
|
}
|
|
|
|
return linkLabel;
|
|
}
|
|
|
|
private void radioButton_Click(object? sender, EventArgs e)
|
|
{
|
|
var id = (int)((RadioButton)sender).Tag;
|
|
taskDialog.OnRadioButtonClicked(id);
|
|
}
|
|
|
|
private void Reset()
|
|
{
|
|
BuildForm();
|
|
|
|
// Setup the default settings.
|
|
if (defaultRadioButton != null)
|
|
{
|
|
defaultRadioButton.Checked = true;
|
|
}
|
|
|
|
// Only can set focus after everything has been build.
|
|
if (taskDialog.DefaultButton != 0)
|
|
{
|
|
// Set the default button.
|
|
if (taskDialogButtons.TryGetValue(taskDialog.DefaultButton, out defaultButton))
|
|
{
|
|
defaultButton.Select();
|
|
}
|
|
else
|
|
{
|
|
if (flowLayoutPanelSubAreaButtons.Controls.Count > 0)
|
|
{
|
|
// Select left-most button.
|
|
flowLayoutPanelSubAreaButtons.Controls[flowLayoutPanelSubAreaButtons.Controls.Count - 1].Select();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (flowLayoutPanelSubAreaButtons.Controls.Count > 0)
|
|
{
|
|
// Set the left-most button to be the default. Dictionary does
|
|
// not keep the order of the button that is added in, so this
|
|
// work around is used.
|
|
//
|
|
// Layout right to left, left-most item is at the end of the list.
|
|
flowLayoutPanelSubAreaButtons.Controls[flowLayoutPanelSubAreaButtons.Controls.Count - 1].Select();
|
|
}
|
|
}
|
|
|
|
timer.Start();
|
|
}
|
|
|
|
private void SetFooterIcon(TaskDialogIcon icon)
|
|
{
|
|
SetFooterIcon(TaskDialog.IconFromTaskDialogIcon(icon));
|
|
}
|
|
|
|
private void SetFooterIcon(Icon icon)
|
|
{
|
|
pictureBoxFooterAreaIcon.Image = TaskDialog.GetSmallImage(icon);
|
|
tableLayoutPanelFooterArea.ColumnStyles[0].Width = pictureBoxFooterAreaIcon.Image?.Width + 6 ?? 0;
|
|
}
|
|
|
|
private void SetFormHeight()
|
|
{
|
|
Height = (tableLayoutPanelMainArea.Height + 32)
|
|
+ tableLayoutPanel1.Height // Separator.
|
|
// When empty, default height is 33. TableLayoutPanel refuses to
|
|
// shrink to 0 as there are items in it.
|
|
+ ((tableLayoutPanelSubArea.Height > 33) ? tableLayoutPanelSubArea.Height : 0)
|
|
+ tableLayoutPanel2.Height // Separator.
|
|
+ ((tableLayoutPanelFooterArea.Height > 0) ? tableLayoutPanelFooterArea.Height : 0)
|
|
+ tableLayoutPanel3.Height // Separator.
|
|
+ tableLayoutPanel4.Height // Separator.
|
|
// When empty, default height is 6. TableLayoutPanel refuses to
|
|
// shrink to 0 as there are items in it.
|
|
+ ((tableLayoutPanelFooterExpandedInformationArea.Height > hPadding) ? tableLayoutPanelFooterExpandedInformationArea.Height : 0);
|
|
}
|
|
|
|
private void SetMainIcon(TaskDialogIcon icon)
|
|
{
|
|
SetMainIcon(TaskDialog.IconFromTaskDialogIcon(icon));
|
|
}
|
|
|
|
private void SetMainIcon(Icon icon)
|
|
{
|
|
pictureBoxMainAreaIcon.Image = icon?.ToBitmap();
|
|
tableLayoutPanelMainArea.ColumnStyles[0].Width = pictureBoxMainAreaIcon.Image?.Width + 10 ?? 0;
|
|
}
|
|
|
|
private void timer_Tick(object? sender, EventArgs e)
|
|
{
|
|
timerTickCount += (uint)timer.Interval;
|
|
|
|
if (taskDialog.OnTimer((int)timerTickCount))
|
|
timerTickCount = 0;
|
|
}
|
|
|
|
private void ToggleExpandedInformationState()
|
|
{
|
|
if (taskDialog.ExpandFooterArea)
|
|
{
|
|
// Shrink/expand our upper "border".
|
|
if (isExpanded)
|
|
{
|
|
tableLayoutPanel3.Visible = tableLayoutPanel4.Visible = false;
|
|
Height -= tableLayoutPanel3.Height * 2;
|
|
}
|
|
else
|
|
{
|
|
tableLayoutPanel3.Visible = tableLayoutPanel4.Visible = true;
|
|
Height += tableLayoutPanel3.Height * 2;
|
|
}
|
|
}
|
|
|
|
if (isExpanded)
|
|
{
|
|
// Shrink the form first.
|
|
Height -= linkLabelExpandedInformation.Height;
|
|
linkLabelExpandedInformation.Visible = false;
|
|
isExpanded = false;
|
|
}
|
|
else
|
|
{
|
|
linkLabelExpandedInformation.Visible = true;
|
|
// Expand the form.
|
|
Height += linkLabelExpandedInformation.Height;
|
|
isExpanded = true;
|
|
}
|
|
}
|
|
|
|
private void verificationCheckBox_Click(object? sender, EventArgs e)
|
|
{
|
|
taskDialog.OnVerificationClicked(((CheckBox)sender).Checked);
|
|
}
|
|
|
|
private static class AdjustControls
|
|
{
|
|
/// <summary>
|
|
/// Measure a multiline string
|
|
/// </summary>
|
|
/// <param name="gr">Graphics</param>
|
|
/// <param name="text">string to measure</param>
|
|
/// <param name="rect">Original rect. The width will be taken as fixed.</param>
|
|
/// <param name="textboxControl">True if you want to measure the string for a textbox control</param>
|
|
/// <returns>A Size object with the measure of the string according with the params</returns>
|
|
public static Size GetBestSize(Graphics gr, string text, Rectangle rect, bool textboxControl)
|
|
{
|
|
RECT bounds = rect;
|
|
using (var dc = new SafeDCHandle(gr))
|
|
{
|
|
var flags = DrawTextFlags.DT_CALCRECT | DrawTextFlags.DT_WORDBREAK;
|
|
if (textboxControl) flags |= DrawTextFlags.DT_EDITCONTROL;
|
|
DrawText(dc, text, text.Length, ref bounds, flags);
|
|
}
|
|
return new Size(bounds.Right - bounds.Left, bounds.Bottom - bounds.Top + (textboxControl ? 6 : 0));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Measure a multiline string for a Control
|
|
///
|
|
/// http://www.mobilepractices.com/2008/01/making-multiline-measurestring-work.html
|
|
/// </summary>
|
|
/// <param name="control">control</param>
|
|
/// <param name="text">string to measure</param>
|
|
/// <param name="rect">Original rect. The width will be taken as fixed.</param>
|
|
/// <returns>A Size object with the measure of the string according with the params</returns>
|
|
public static Size GetBestSize(Control control, string text, Rectangle rect)
|
|
{
|
|
Size result;
|
|
using (var gr = control.CreateGraphics())
|
|
using (var hDC = new SafeDCHandle(gr))
|
|
using (new SafeDCObjectHandle(hDC, control.Font.ToHfont()))
|
|
result = GetBestSize(gr, text, rect, control is TextBox);
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif |