📄 messageboxform.cs
字号:
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
namespace NonFullscreenDemo
{
public partial class MessageBoxForm : NonFullscreenForm
{
private SizeF MyAutoScaleFactor;
private MessageBeepType beepType = MessageBeepType.Default;
#region Native Platform Invoke
[DllImport("coredll.dll")]
private static extern int MessageBeep(MessageBeepType uType);
[DllImport("coredll.dll")]
private static extern int DrawText(IntPtr hDC, string lpString, int nCount, ref RECT lpRect, uint uFormat);
[DllImport("coredll.dll")]
private static extern IntPtr SelectObject(IntPtr hDC, IntPtr hobj);
[DllImport("coredll.dll")]
private static extern int DeleteObject(IntPtr HGDIOBJ);
public enum MessageBeepType : uint
{
None = 0xFFFFFFFE,
Simple = 0xFFFFFFFF, // Simple beep
Default = 0x00000000, // MB_OK
SystemHand = 0x00000010, // MB_ICONHAND
SystemQuestion = 0x00000020, // MB_ICONQUESTION
SystemExclamation = 0x00000030, // MB_ICONEXCLAMATION
SystemAsterisk = 0x00000040 // MB_ICONASTERISK
}
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(Rectangle rc)
{
this.Left = rc.Left;
this.Right = rc.Right;
this.Top = rc.Top;
this.Bottom = rc.Bottom;
}
}
private static readonly uint DT_LEFT = 0x00000000;
private static readonly uint DT_TOP = 0x00000000;
private static readonly uint DT_WORDBREAK = 0x00000010;
private static readonly uint DT_CALCRECT = 0x00000400;
private static readonly uint DT_NOPREFIX = 0x00000800;
#endregion
private MessageBoxForm()
{
InitializeComponent();
// We have a couple of coordinates specified within this
// class. The coordinates are calculated assuming a 96DPI
// screen. Calculate a scaling factor to translate these
// coordinates into the required values for the current
// screen's DPI.
MyAutoScaleFactor = new SizeF(
this.AutoScaleDimensions.Width / 96F,
this.AutoScaleDimensions.Height / 96F);
}
/// <summary>
/// Displays a message box to the user with a blank caption and a single
/// [OK] button on the caption.
/// </summary>
/// <param name="owner">The form which is wanting to display this message box.</param>
/// <param name="message">The message to display in the client area of the message box.</param>
/// <param name="caption">The title to display in the caption of the message box.</param>
/// <returns>DialogResult.OK</returns>
public static DialogResult Show(Form owner, string message)
{
return Show(owner, message, null, null);
}
/// <summary>
/// Displays a message box to the user with a single [OK] button on the caption.
/// </summary>
/// <param name="owner">The form which is wanting to display this message box.</param>
/// <param name="message">The message to display in the client area of the message box.</param>
/// <param name="caption">The title to display in the caption of the message box.</param>
/// <returns>DialogResult.OK</returns>
public static DialogResult Show(Form owner, string message, string caption)
{
return Show(owner, message, caption, null);
}
/// <summary>
/// Displays a message box to the user with a blank caption.
/// </summary>
/// <param name="owner">The form which is wanting to display this message box.</param>
/// <param name="message">The message to display in the client area of the message box.</param>
/// <param name="buttons">A dictionary containing button labels (and their respective DialogResult values).</param>
/// <returns>The DialogResult value of the button which caused the message box to dismiss.</returns>
public static DialogResult Show(Form owner, string message, Dictionary<string, DialogResult> buttons)
{
return Show(owner, message, null, buttons);
}
/// <summary>
/// Displays a message box to the user.
/// </summary>
/// <param name="owner">The form which is wanting to display this message box.</param>
/// <param name="message">The message to display in the client area of the message box.</param>
/// <param name="caption">The title to display in the caption of the message box.</param>
/// <param name="buttons">A dictionary containing button labels (and their respective DialogResult values).</param>
/// <returns>The DialogResult value of the button which caused the message box to dismiss.</returns>
public static DialogResult Show(Form owner, string message, string caption, Dictionary<string, DialogResult> buttons)
{
// Create a new MessageBoxForm and configure the
// caption and message text strings.
MessageBoxForm form = new MessageBoxForm();
form.Owner = owner;
form.Text = caption;
form.lblMessage.Text = message;
// We only want the ControlBox (i.e. the [OK] button) if
// there are no custom buttons for this message box
form.ControlBox = (buttons == null || buttons.Count == 0);
// Resize the form to make it just large enough to fit
// the contents and no larger.
SizeFormToContent(form, !form.ControlBox);
// Add the desired buttons to the form. They are all
// docked left into a container panel, so that we
// don't need to bother with manual co-ordinate
// calculations within this class.
if (!form.ControlBox)
{
form.SuspendLayout();
int buttonWidth = (form.pnlButtons.Width - (int)(form.MyAutoScaleFactor.Width * 2) - (buttons.Count - 1) * form.pnlButtons.Left) / buttons.Count;
foreach (KeyValuePair<string, DialogResult> kp in buttons)
{
// Add a button to the form
Button button = new Button();
button.Text = kp.Key;
button.DialogResult = kp.Value;
button.Dock = DockStyle.Left;
button.Width = buttonWidth;
form.pnlButtons.Controls.Add(button);
form.pnlButtons.Controls.SetChildIndex(button, 0);
// Add a seperator panel to the form to
// seperate this button from the next one
Panel seperator = new Panel();
seperator.Width = form.pnlButtons.Left;
seperator.Dock = DockStyle.Left;
form.pnlButtons.Controls.Add(seperator);
form.pnlButtons.Controls.SetChildIndex(seperator, 0);
}
form.ResumeLayout();
}
// Finally we are ready to
// display the dialog box...
return form.ShowDialog();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// When the message box is displayed play
// the desired sound effect
if (beepType != MessageBeepType.None)
{
MessageBeep(beepType);
}
}
// Calculate how big we want the message box text label
// to be to fit the user's specified text
private static Size CalcTextSize(MessageBoxForm form)
{
RECT bounds = new RECT(form.lblMessage.ClientRectangle);
int titleWidth;
// Measure how tall/wide the text will be assuming we
// can't go wider than the maximum width of the label.
using (Graphics g = form.CreateGraphics())
{
IntPtr hdc = IntPtr.Zero;
IntPtr hFont = IntPtr.Zero;
try
{
hdc = g.GetHdc();
hFont = form.lblMessage.Font.ToHfont();
// Get the Drawtext Win32 API to measure the width and height of the
// text. Using the width specified in bounds.Right - bounds.Left to
// dictate the word wrapping behaviour.
IntPtr oldFont = SelectObject(hdc, hFont);
DrawText(hdc, form.lblMessage.Text, form.lblMessage.Text.Length, ref bounds, DT_LEFT | DT_TOP | DT_CALCRECT | DT_NOPREFIX | DT_WORDBREAK);
SelectObject(hdc, oldFont);
// Calculate how wide the caption will be (roughly)
titleWidth = (int)(g.MeasureString(form.Text, form.Font).Width * 1.5) + SystemInformation.MenuHeight;
}
finally
{
// Tidy up our native resources
if (hFont != IntPtr.Zero)
{
DeleteObject(hFont);
}
if (hdc != IntPtr.Zero)
{
g.ReleaseHdc(hdc);
}
}
}
// Return a rectangle just large enough to hold the
// message we want to display. Very narrow dialogs look
// ugly and probably don't leave enough space for the
// caption, so if the width would be narrower than
// what we roughly calculate is required to make the
// caption fully visible, we use this width instead.
// This seems to give a behaviour similiar to the
// Win32 MessageBox API.
if ((bounds.Right - bounds.Left) < titleWidth)
return new Size(titleWidth, bounds.Bottom - bounds.Top);
else
return new Size(bounds.Right - bounds.Left + (int)(form.MyAutoScaleFactor.Width * 4), bounds.Bottom - bounds.Top);
}
private static void SizeFormToContent(MessageBoxForm form, bool hasButtons)
{
// Only show the panel of buttons if we
// have atleast one button to display...
form.pnlButtons.Visible = hasButtons;
// We'll limit the width of our message box form to
// 3/4ths of the working area of the screen.
form.Width = Screen.PrimaryScreen.WorkingArea.Width / 4 * 3;
// Figure out how big we need to make our text label
// to display the user's message
Size textSize = CalcTextSize(form);
// And based upon this, calculate and then eventually
// set the form's size so that the label is of the
// correct size (due to it's anchoring, as we resize
// the form we'll also resize the label automatically).
int width = 2 * form.lblMessage.Left + textSize.Width;
int height = 2 * form.lblMessage.Top + textSize.Height;
if (hasButtons)
height += form.lblMessage.Top + form.pnlButtons.Height;
form.Size = new Size(width, height);
form.lblMessage.Height = textSize.Height;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -