Skip to content

Instantly share code, notes, and snippets.

@Tewr
Last active November 18, 2021 18:27
Show Gist options
  • Save Tewr/6ad6225d1e961197d681ece7b5726ca0 to your computer and use it in GitHub Desktop.
Save Tewr/6ad6225d1e961197d681ece7b5726ca0 to your computer and use it in GitHub Desktop.
Winforms MessageBoxWithCheckBox
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace CustomMessageBoxes
{
public partial class MessageBoxWithCheckBox : Form
{
private MessageBoxButtons _messageBoxButtons;
public MessageBoxWithCheckBox()
{
InitializeComponent();
this.messageLabel.Font = SystemFonts.MessageBoxFont;
this.checkBox.Font = SystemFonts.MessageBoxFont;
}
private static readonly IReadOnlyDictionary<MessageBoxIcon, NativeIcons.SHSTOCKICONID> NativeIconMap =
new Dictionary<MessageBoxIcon, NativeIcons.SHSTOCKICONID>
{
{ MessageBoxIcon.Information, NativeIcons.SHSTOCKICONID.SIID_INFO },
{ MessageBoxIcon.Warning, NativeIcons.SHSTOCKICONID.SIID_WARNING },
{ MessageBoxIcon.Error, NativeIcons.SHSTOCKICONID.SIID_ERROR },
{ MessageBoxIcon.Question, NativeIcons.SHSTOCKICONID.SIID_HELP },
};
private static readonly IReadOnlyDictionary<MessageBoxButtons, DialogResult> LeftButtonResults =
new Dictionary<MessageBoxButtons, DialogResult>
{
{ MessageBoxButtons.YesNo, DialogResult.Yes },
{ MessageBoxButtons.OKCancel, DialogResult.OK },
};
private static readonly IReadOnlyDictionary<MessageBoxButtons, string> LeftButtonCaptions =
new Dictionary<MessageBoxButtons, string>
{
{ MessageBoxButtons.YesNo, "&Yes" },
{ MessageBoxButtons.OKCancel, "&OK" },
};
private static readonly IReadOnlyDictionary<MessageBoxButtons, DialogResult> RightButtonResults =
new Dictionary<MessageBoxButtons, DialogResult>
{
{ MessageBoxButtons.YesNo, DialogResult.No },
{ MessageBoxButtons.OKCancel, DialogResult.Cancel },
{ MessageBoxButtons.OK, DialogResult.OK },
};
private static readonly IReadOnlyDictionary<MessageBoxButtons, string> RightButtonCaptions =
new Dictionary<MessageBoxButtons, string>
{
{ MessageBoxButtons.YesNo, "&No" },
{ MessageBoxButtons.OKCancel, "&Cancel" },
{ MessageBoxButtons.OK, "&OK" },
};
public static Tuple<DialogResult, bool> Show(string caption, string title, string checkboxCaption, bool checkboxChecked, MessageBoxButtons messageBoxButtons, MessageBoxIcon information)
{
if (!RightButtonCaptions.ContainsKey(messageBoxButtons))
{
throw new NotSupportedException($"{messageBoxButtons} not supported for {nameof(messageBoxButtons)}");
}
var f = new MessageBoxWithCheckBox
{
Text = title,
checkBox = { Text = checkboxCaption, Checked = checkboxChecked },
messageLabel = { Text = caption },
_messageBoxButtons = messageBoxButtons,
leftButton = {
Text = messageBoxButtons != MessageBoxButtons.OK ? LeftButtonCaptions[messageBoxButtons] : string.Empty,
Visible = messageBoxButtons != MessageBoxButtons.OK },
rightButton = { Text = RightButtonCaptions[messageBoxButtons] }
};
ResizeLabelAndConsequentlyTheWholeForm(f);
NativeIcons.SHSTOCKICONID nativeIconreference;
if (NativeIconMap.TryGetValue(information, out nativeIconreference))
{
f.iconPictureBox.Image = NativeIcons.GetSystemIconBmp(nativeIconreference);
}
return Tuple.Create(f.ShowDialog(), f.checkBox.Checked);
}
protected override CreateParams CreateParams
{
get
{
// ReSharper disable once InconsistentNaming
const int CP_NOCLOSE_BUTTON = 0x200;
var myCp = base.CreateParams;
myCp.ClassStyle = myCp.ClassStyle | CP_NOCLOSE_BUTTON;
return myCp;
}
}
private static void ResizeLabelAndConsequentlyTheWholeForm(MessageBoxWithCheckBox f)
{
var niceToBeSize = TextRenderer.MeasureText(f.messageLabel.Text, f.messageLabel.Font);
var additionalMargin = TextRenderer.MeasureText("WW", f.messageLabel.Font);
f.messageLabel.Size = new Size(niceToBeSize.Width + f.messageLabel.Padding.Left + f.messageLabel.Padding.Right + additionalMargin.Width,
niceToBeSize.Height + f.messageLabel.Padding.Top + f.messageLabel.Padding.Bottom + additionalMargin.Height);
}
private void LeftButtonClick(object sender, EventArgs e)
{
DialogResult = LeftButtonResults[_messageBoxButtons];
}
private void RightButtonClick(object sender, EventArgs e)
{
DialogResult = RightButtonResults[_messageBoxButtons];
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
e.Cancel = true;
base.OnFormClosing(e);
}
[SuppressMessage("ReSharper", "UnusedMember.Local")]
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
[SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")]
private static class NativeIcons
{
public static Bitmap GetSystemIconBmp(SHSTOCKICONID icon)
{
SHSTOCKICONINFO sii = new SHSTOCKICONINFO
{
cbSize = (UInt32) Marshal.SizeOf(typeof(SHSTOCKICONINFO))
};
Marshal.ThrowExceptionForHR(SHGetStockIconInfo(icon,
SHGSI.SHGSI_ICON,
ref sii));
var bmp = new Bitmap(Icon.FromHandle(sii.hIcon).ToBitmap());
DestroyIcon(sii.hIcon);
return bmp;
}
#pragma warning disable S2342 // Enumeration types should comply with a naming convention
public enum SHSTOCKICONID : uint
#pragma warning restore S2342 // Enumeration types should comply with a naming convention
{
SIID_DOCNOASSOC = 0,
SIID_DOCASSOC = 1,
SIID_APPLICATION = 2,
SIID_FOLDER = 3,
SIID_FOLDEROPEN = 4,
SIID_DRIVE525 = 5,
SIID_DRIVE35 = 6,
SIID_DRIVEREMOVE = 7,
SIID_DRIVEFIXED = 8,
SIID_DRIVENET = 9,
SIID_DRIVENETDISABLED = 10,
SIID_DRIVECD = 11,
SIID_DRIVERAM = 12,
SIID_WORLD = 13,
SIID_SERVER = 15,
SIID_PRINTER = 16,
SIID_MYNETWORK = 17,
SIID_FIND = 22,
SIID_HELP = 23,
SIID_SHARE = 28,
SIID_LINK = 29,
SIID_SLOWFILE = 30,
SIID_RECYCLER = 31,
SIID_RECYCLERFULL = 32,
SIID_MEDIACDAUDIO = 40,
SIID_LOCK = 47,
SIID_AUTOLIST = 49,
SIID_PRINTERNET = 50,
SIID_SERVERSHARE = 51,
SIID_PRINTERFAX = 52,
SIID_PRINTERFAXNET = 53,
SIID_PRINTERFILE = 54,
SIID_STACK = 55,
SIID_MEDIASVCD = 56,
SIID_STUFFEDFOLDER = 57,
SIID_DRIVEUNKNOWN = 58,
SIID_DRIVEDVD = 59,
SIID_MEDIADVD = 60,
SIID_MEDIADVDRAM = 61,
SIID_MEDIADVDRW = 62,
SIID_MEDIADVDR = 63,
SIID_MEDIADVDROM = 64,
SIID_MEDIACDAUDIOPLUS = 65,
SIID_MEDIACDRW = 66,
SIID_MEDIACDR = 67,
SIID_MEDIACDBURN = 68,
SIID_MEDIABLANKCD = 69,
SIID_MEDIACDROM = 70,
SIID_AUDIOFILES = 71,
SIID_IMAGEFILES = 72,
SIID_VIDEOFILES = 73,
SIID_MIXEDFILES = 74,
SIID_FOLDERBACK = 75,
SIID_FOLDERFRONT = 76,
SIID_SHIELD = 77,
SIID_WARNING = 78,
SIID_INFO = 79,
SIID_ERROR = 80,
SIID_KEY = 81,
SIID_SOFTWARE = 82,
SIID_RENAME = 83,
SIID_DELETE = 84,
SIID_MEDIAAUDIODVD = 85,
SIID_MEDIAMOVIEDVD = 86,
SIID_MEDIAENHANCEDCD = 87,
SIID_MEDIAENHANCEDDVD = 88,
SIID_MEDIAHDDVD = 89,
SIID_MEDIABLURAY = 90,
SIID_MEDIAVCD = 91,
SIID_MEDIADVDPLUSR = 92,
SIID_MEDIADVDPLUSRW = 93,
SIID_DESKTOPPC = 94,
SIID_MOBILEPC = 95,
SIID_USERS = 96,
SIID_MEDIASMARTMEDIA = 97,
SIID_MEDIACOMPACTFLASH = 98,
SIID_DEVICECELLPHONE = 99,
SIID_DEVICECAMERA = 100,
SIID_DEVICEVIDEOCAMERA = 101,
SIID_DEVICEAUDIOPLAYER = 102,
SIID_NETWORKCONNECT = 103,
SIID_INTERNET = 104,
SIID_ZIPFILE = 105,
SIID_SETTINGS = 106,
SIID_DRIVEHDDVD = 132,
SIID_DRIVEBD = 133,
SIID_MEDIAHDDVDROM = 134,
SIID_MEDIAHDDVDR = 135,
SIID_MEDIAHDDVDRAM = 136,
SIID_MEDIABDROM = 137,
SIID_MEDIABDR = 138,
SIID_MEDIABDRE = 139,
SIID_CLUSTEREDDRIVE = 140,
SIID_MAX_ICONS = 175
}
[Flags]
#pragma warning disable S2342 // Enumeration types should comply with a naming convention
// ReSharper disable once InconsistentNaming
private enum SHGSI : uint
#pragma warning restore S2342 // Enumeration types should comply with a naming convention
{
#pragma warning disable S2346 // Flags enumerations zero-value members should be named "None"
SHGSI_ICONLOCATION = 0,
#pragma warning restore S2346 // Flags enumerations zero-value members should be named "None"
SHGSI_ICON = 0x000000100,
SHGSI_SYSICONINDEX = 0x000004000,
SHGSI_LINKOVERLAY = 0x000008000,
SHGSI_SELECTED = 0x000010000,
SHGSI_LARGEICON = 0x000000000,
SHGSI_SMALLICON = 0x000000001,
SHGSI_SHELLICONSIZE = 0x000000004
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
#pragma warning disable S101 // Types should be named in camel case
private struct SHSTOCKICONINFO
#pragma warning restore S101 // Types should be named in camel case
{
public UInt32 cbSize;
#pragma warning disable S3459 // Unassigned members should be removed
public IntPtr hIcon;
#pragma warning restore S3459 // Unassigned members should be removed
public Int32 iSysIconIndex;
public Int32 iIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260 /*MAX_PATH*/)] public string szPath;
}
[DllImport("Shell32.dll", SetLastError = false)]
private static extern Int32 SHGetStockIconInfo(SHSTOCKICONID siid, SHGSI uFlags, ref SHSTOCKICONINFO psii);
[DllImport("user32.dll", SetLastError = true)]
static extern bool DestroyIcon(IntPtr hIcon);
}
}
}
namespace CustomMessageBoxes
{
partial class MessageBoxWithCheckBox
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <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 != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.messageLabel = new System.Windows.Forms.Label();
this.leftButton = new System.Windows.Forms.Button();
this.iconPictureBox = new System.Windows.Forms.PictureBox();
this.rightButton = new System.Windows.Forms.Button();
this.messageAreaPanel = new System.Windows.Forms.Panel();
this.checkBox = new System.Windows.Forms.CheckBox();
this.checkBoxAreaPanel = new System.Windows.Forms.Panel();
((System.ComponentModel.ISupportInitialize)(this.iconPictureBox)).BeginInit();
this.messageAreaPanel.SuspendLayout();
this.checkBoxAreaPanel.SuspendLayout();
this.SuspendLayout();
//
// messageLabel
//
this.messageLabel.BackColor = System.Drawing.SystemColors.ControlLightLight;
this.messageLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.messageLabel.Location = new System.Drawing.Point(195, 57);
this.messageLabel.Name = "messageLabel";
this.messageLabel.Size = new System.Drawing.Size(696, 109);
this.messageLabel.TabIndex = 0;
this.messageLabel.Text = "messageLabel";
//
// leftButton
//
this.leftButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.leftButton.Location = new System.Drawing.Point(407, 364);
this.leftButton.Name = "leftButton";
this.leftButton.Size = new System.Drawing.Size(234, 64);
this.leftButton.TabIndex = 2;
this.leftButton.Text = "&Yes";
this.leftButton.UseVisualStyleBackColor = true;
this.leftButton.Click += new System.EventHandler(this.LeftButtonClick);
//
// iconPictureBox
//
this.iconPictureBox.Location = new System.Drawing.Point(60, 57);
this.iconPictureBox.Name = "iconPictureBox";
this.iconPictureBox.Size = new System.Drawing.Size(105, 90);
this.iconPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.iconPictureBox.TabIndex = 3;
this.iconPictureBox.TabStop = false;
//
// rightButton
//
this.rightButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.rightButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.rightButton.Location = new System.Drawing.Point(669, 364);
this.rightButton.Name = "rightButton";
this.rightButton.Size = new System.Drawing.Size(241, 64);
this.rightButton.TabIndex = 3;
this.rightButton.Text = "&No";
this.rightButton.UseVisualStyleBackColor = true;
this.rightButton.Click += new System.EventHandler(this.RightButtonClick);
//
// messageAreaPanel
//
this.messageAreaPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.messageAreaPanel.AutoSize = true;
this.messageAreaPanel.BackColor = System.Drawing.SystemColors.ControlLightLight;
this.messageAreaPanel.Controls.Add(this.messageLabel);
this.messageAreaPanel.Controls.Add(this.iconPictureBox);
this.messageAreaPanel.Location = new System.Drawing.Point(-1, -4);
this.messageAreaPanel.Name = "messageAreaPanel";
this.messageAreaPanel.Size = new System.Drawing.Size(956, 215);
this.messageAreaPanel.TabIndex = 5;
//
// checkBox
//
this.checkBox.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.checkBox.Location = new System.Drawing.Point(192, 32);
this.checkBox.Name = "checkBox";
this.checkBox.Size = new System.Drawing.Size(696, 62);
this.checkBox.TabIndex = 1;
this.checkBox.Text = "checkBox";
this.checkBox.UseVisualStyleBackColor = true;
//
// checkBoxAreaPanel
//
this.checkBoxAreaPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.checkBoxAreaPanel.BackColor = System.Drawing.SystemColors.ControlLightLight;
this.checkBoxAreaPanel.Controls.Add(this.checkBox);
this.checkBoxAreaPanel.Location = new System.Drawing.Point(-1, 211);
this.checkBoxAreaPanel.Name = "checkBoxAreaPanel";
this.checkBoxAreaPanel.Size = new System.Drawing.Size(956, 120);
this.checkBoxAreaPanel.TabIndex = 6;
//
// MessageBoxWithCheckBox
//
this.AcceptButton = this.leftButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(19F, 37F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.CausesValidation = false;
this.ClientSize = new System.Drawing.Size(957, 464);
this.Controls.Add(this.checkBoxAreaPanel);
this.Controls.Add(this.messageAreaPanel);
this.Controls.Add(this.rightButton);
this.Controls.Add(this.leftButton);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(784, 512);
this.Name = "MessageBoxWithCheckBox";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "MessageBoxWithCheckBox";
this.TopMost = true;
((System.ComponentModel.ISupportInitialize)(this.iconPictureBox)).EndInit();
this.messageAreaPanel.ResumeLayout(false);
this.checkBoxAreaPanel.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label messageLabel;
private System.Windows.Forms.Button leftButton;
private System.Windows.Forms.PictureBox iconPictureBox;
private System.Windows.Forms.Button rightButton;
private System.Windows.Forms.Panel messageAreaPanel;
private System.Windows.Forms.CheckBox checkBox;
private System.Windows.Forms.Panel checkBoxAreaPanel;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment