65.9K
CodeProject 正在变化。 阅读更多。
Home

自定义功能的 MessageBox

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.80/5 (9投票s)

2008 年 1 月 9 日

CPOL

5分钟阅读

viewsIcon

55071

downloadIcon

1052

一个如我们所愿的消息框。

引言

在开发程序时,我们经常需要使用 MessageBox,它是与用户沟通的非常有用的工具。有时,我们希望 MessageBox 看起来像我们应用程序的一部分,或者与应用程序的主题相匹配,但这可能并不总是可行的。例如,我们在应用程序中将 LightSkyBlue 用作所有窗体的背景色,但当我们显示 MessageBox 时,它的样式始终是相同的。在这种组合中,MessageBox 会显得很奇怪。换句话说,我们对 MessageBox 控件没有完全的控制权。那么,为什么我们不制作一个我们想要的消息框,这样我们就可以完全控制它呢?

我浪费了很多宝贵的时间来寻找解决方案,但从未找到。于是,我计划自己做一个。经过大量的研发,我终于做到了。现在,我认为我应该与遇到相同问题的人分享我的解决方案。在本文的最后,读者将拥有一个自定义的 MessageBox,并且可以对其进行完全控制。

设计

创建一个新项目,命名为“Custom Featured MessageBox”,打开其属性,并将“Output Type”设置为“Class Library”(因为 Class Library 输出是一个 DLL,可以轻松地添加到任何项目中)。在同一个解决方案中添加一个新项目,命名为“Test”,右键单击它,然后选择“Set as StartUp Project”。现在,回到“Custom Featured MessageBox”项目。

我们将需要

  • 一个 Windows 窗体
  • 一个 PictureBox,用于显示图标
  • 一个 TextBox,用于显示文本(这里不能使用 Label,因为我们需要计算行数)
  • 三个 Buttons,用于对话框结果
  • 三个 Panels,用于将所有控件放置在正确的位置和大小

设置控件属性如下

Form:
Name: XMessageBox
ControlBox: False
FormBorderStyle: FixedSingle
Max.Box: False
Min.Box: False
Padding: 10, 10, 10, 0
ShowIcon: False
ShowInTaskbar: False
Size: 262, 104
StartPosition: CenterScreen

TextBox:
BackColor: Control
BorderStyle: None
Dock: Fill
MaxLength: 0 (i.e. Max Length)
Multiline: True
ReadOnly: True
TabStop: False
TextAlign: Center

Panels:

Panel 1:
Name: leftPanel
Dock: Left
Visible: False
    Controls:
           PictureBox
Panel 2:
Name: bottomPanel
Dock: Bottom
    Controls:
           Panel 3
Panel 3 :
Name: bottomInnerPanel
Location: 0, 0
Size: 236, 30
    Controls:
           Button 1
           Button 2
           Button 3

PictureBox:
BackgroundImageLayout: Stretch
Location: 0, 0
Size: 32, 32

Button 1:
Location: 0, 3
Visible: False

Button 2:
Location: 81, 3
Visible: False

Button 3:
Location: 162, 3
Visible: False

做得好!现在,它看起来会像这样

1.jpg

使用代码

首先,创建两个类型为 intconst 成员变量。

const int minWidth = 262;
const int maxWidth = 600;

然后,我们需要创建两个 enums,XMessageBoxButtonsXMessageBoxIcon,并带有 public 修饰符

public enum XMessageBoxButtons
{ OK, AbortRetryIgnore, YesNoCancel, YesNo, RetryCancel, }
public enum XMessageBoxIcon
{ Error, Question, Warning, Information, }

在此之后,创建两个方法 SetButtonsSetIcon,分别用于设置按钮和图标

void SetButtons(XMessageBoxButtons buttons)
{
    if (buttons == XMessageBoxButtons.OK)
    {
        button2.Visible = true;
        button2.Text = "OK";
        button2.DialogResult = DialogResult.OK;
        ControlBox = true;
    }
    else if (buttons == XMessageBoxButtons.AbortRetryIgnore)
    {
        button1.Visible = true;
        button1.Text = "Abort";
        button1.DialogResult = DialogResult.Abort;
        button2.Visible = true;
        button2.Text = "Retry";
        button2.DialogResult = DialogResult.Retry;
        button3.Visible = true;
        button3.Text = "Ignore";
        button3.DialogResult = DialogResult.Ignore;
        if (this.Width < minWidth)
            this.Width = minWidth;
    }
    else if (buttons == XMessageBoxButtons.RetryCancel)
    {
        button1.Visible = true;
        button1.Text = "Retry";
        button1.DialogResult = DialogResult.Retry;
        button1.Location = new Point(41, 3);
        button2.Visible = true;
        button2.Text = "Cancel";
        button2.DialogResult = DialogResult.Cancel;
        button2.Location = new Point(122, 3);
        if (this.Width < minWidth)
            this.Width = minWidth;
    }
    else if (buttons == XMessageBoxButtons.YesNo)
    {
        button1.Visible = true;
        button1.Text = "Yes";
        button1.DialogResult = DialogResult.Yes;
        button1.Location = new Point(41, 3);
        button2.Visible = true;
        button2.Text = "No";
        button2.DialogResult = DialogResult.No;
        button2.Location = new Point(122, 3);
        if (this.Width < minWidth)
            this.Width = minWidth;
    }
    else if (buttons == XMessageBoxButtons.YesNoCancel)
    {
        button1.Visible = true;
        button1.DialogResult = DialogResult.Yes;
        button1.Text = "Yes";
        button2.Visible = true;
        button2.DialogResult = DialogResult.No;
        button2.Text = "No";
        button3.Visible = true;
        button3.DialogResult = DialogResult.Cancel;
        button3.Text = "Cancel";
        if (this.Width < minWidth)
            this.Width = minWidth;
    }
}

void SetIcon(XMessageBoxIcon icon)
{
    if (this.Height < 104)
        this.Height = 104;
    if (this.Width <= 600)
        this.Width += 55;
    leftPanel.Visible = true;
    if (icon == XMessageBoxIcon.Information)
        pictureBox1.BackgroundImage = 
          Custom_Featured_MessageBox.Properties.Resources.Information; 
    // Images have been added to Resources
    else if (icon == XMessageBoxIcon.Warning)
        pictureBox1.BackgroundImage = 
          Custom_Featured_MessageBox.Properties.Resources.Warning;
    else if (icon == XMessageBoxIcon.Error)
        pictureBox1.BackgroundImage = 
          Custom_Featured_MessageBox.Properties.Resources.Error;
    else if (icon == XMessageBoxIcon.Question)
        pictureBox1.BackgroundImage = 
          Custom_Featured_MessageBox.Properties.Resources.QuestionMark;
}

现在,我们应该创建一个方法来设置整个消息框。将其命名为 XmessageBox,并带有七个参数

void XmessageBox(string text, string title, Size size, Font font, 
     Color backColor, Color foreColor, bool customSize)
{}

接下来,在其中编写代码,以便在调用时可以设置消息框

int width;
int height;

this.Text = title;
TextBox1.Text = text;
this.Font = font;
this.BackColor = backColor;
this.ForeColor = foreColor;

Graphics g = this.CreateGraphics(); // Initiating
SizeF textSize = g.MeasureString(text, font);
g.Dispose();
//|==================================================//
//|------------                                      //
//|CALCULATIONS                                      //
//|------------                                      //            
//|15, adjustment                                    //
//|==================================================//            
if (textSize.Width <= maxWidth)
    width = (int)textSize.Width + 15;
else
    width = maxWidth;

//|==================================================//
//|------------                                      //
//|CALCULATIONS                                      //
//|------------                                      //
//|30 + 10 = 40, panal height + form's top padding   //            
//|40, adjustment                                    //
//|==================================================//
height = (TextBox1.Lines.Length * TextBox1.Font.Height) + 40 + 40;

if (customSize == true)  // set size only when customSize is true
    this.Size = size;
else
    this.Size = new Size(width, height);

完成后,选择窗体 (XMessageBox),双击 Resize 事件,并编写这两行,以将所有对话框按钮置于窗体中央。

int x = (bottomPanel.Width - bottomInnerPanel.Width) / 2;
bottomInnerPanel.Location = new Point(x, bottomInnerPanel.Location.Y); // Y will same

另外,双击 BackColorChangedForeColorChanged 事件,以便在窗体颜色更改时设置 Textbox1 的颜色。

private void XMessageBox_ForeColorChanged(object sender, EventArgs e)
{
    TextBox1.ForeColor = this.ForeColor;
}
private void XMessageBox_BackColorChanged(object sender, EventArgs e)
{
    TextBox1.BackColor = this.BackColor;
}

创建一个 static 方法来显示 XMessageBox(因为 static 方法可以在不创建实例的情况下调用)。将其命名为 show,带有一个参数和一个 DialogResult 返回类型。

public static  DialogResult show(string text)
{}

在此编写代码

XMessageBox f = new XMessageBox();
f.XmessageBox(text, "", f.Size, f.Font, f.BackColor, f.ForeColor, false);
f.SetButtons(XMessageBoxButtons.OK); // if button is not specified, then set OK
return f.ShowDialog();

在此代码中,我们创建了 XMessageBox 的一个实例并调用了它的一些必需方法。我们在此处未调用 SetIcon,因为此 static 方法仅显示一个简单的消息框。

接下来,添加十二个更多方法来重载此方法

public static DialogResult show(string text, string title)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, f.Size, f.Font, f.BackColor, f.ForeColor, false);
    f.SetButtons(XMessageBoxButtons.OK); // if button is not specified
    return f.ShowDialog();
}
public static 
    DialogResult show(string text, string title, XMessageBoxButtons buttons)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, f.Size, f.Font, f.BackColor, f.ForeColor, false);
    f.SetButtons(buttons);
    return f.ShowDialog();
}
public static DialogResult show(string text, string title, 
       XMessageBoxButtons buttons, XMessageBoxIcon icon)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, f.Size, f.Font, f.BackColor, f.ForeColor, false);
    f.SetButtons(buttons);
    f.SetIcon(icon);
    return f.ShowDialog();
}
public static DialogResult show(string text, string title, 
              XMessageBoxButtons buttons, Size size)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, size, f.Font, f.BackColor, f.ForeColor, true);
    f.SetButtons(buttons);
    return f.ShowDialog();
}

public static DialogResult show(string text, string title, 
              XMessageBoxButtons buttons, XMessageBoxIcon icon, Size size)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, size, f.Font, f.BackColor, f.ForeColor, true);
    f.SetButtons(buttons);
    f.SetIcon(icon);
    return f.ShowDialog();
}
public static DialogResult show(string text, string title, 
              XMessageBoxButtons buttons, Size size, Font font)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, size, font, f.BackColor, f.ForeColor, true);
    f.SetButtons(buttons);
    return f.ShowDialog();
}
public static DialogResult show(string text, string title, XMessageBoxButtons buttons, 
              XMessageBoxIcon icon, Size size, Font font)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, size, font, f.BackColor, f.ForeColor, true);
    f.SetButtons(buttons);
    f.SetIcon(icon);
    return f.ShowDialog();
}
public static DialogResult show(string text, string title, 
              Color backColor, Color foreColor)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, f.Size, f.Font, backColor, foreColor, false);
    f.SetButtons(XMessageBoxButtons.OK);
    return f.ShowDialog();
}
public static DialogResult show(string text, string title, 
       Color backColor, Color foreColor, XMessageBoxButtons buttons)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, f.Size, f.Font, backColor, foreColor, false);
    f.SetButtons(buttons);
    return f.ShowDialog();
}
public static DialogResult show(string text, string title, Color backColor, 
              Color foreColor, XMessageBoxButtons buttons, XMessageBoxIcon icon)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, f.Size, f.Font, backColor, foreColor, false);
    f.SetButtons(buttons);
    f.SetIcon(icon);
    return f.ShowDialog();
}
public static DialogResult show(string text, string title, Color backColor, 
              Color foreColor, XMessageBoxButtons buttons, Size size, Font font)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, size, font, backColor, foreColor, true);
    f.SetButtons(buttons);
    return f.ShowDialog();
}
public static DialogResult show(string text, string title, Color backColor, Color foreColor, 
              XMessageBoxButtons buttons, XMessageBoxIcon icon, Size size, Font font)
{
    XMessageBox f = new XMessageBox();
    f.XmessageBox(text, title, size, font, backColor, foreColor, true);
    f.SetButtons(buttons);
    f.SetIcon(icon);
    return f.ShowDialog();
}

回到 Test 项目,右键单击“References”,选择“Add Reference…”,然后切换到“Projects”选项卡,选择“Custom Featured MessageBox”后按“OK”。完成后,在 Form1 中添加命名空间引用。

using Custom_Featured_MessageBox;

添加一个 Button,双击它,并编写代码

XMessageBox.show("Simple MessageBox with OK button, BackColor is LightSkyBlue " + 
                 "and ForeColor is Black.", "Example", 
                 Color.LightSkyBlue, Color.Black, XMessageBoxButtons.OK);
XMessageBox.show("Simple MessageBox with Abort, Retry and Ignore buttons, BackColor" + 
                 " is LightCyan and ForeColor is Black.", "Example", 
                 Color.LightCyan, Color.Black, XMessageBoxButtons.AbortRetryIgnore);
XMessageBox.show("Error MessageBox with OK button, BackColor is LightGreen " + 
                 "and ForeColor is Black.", "Example", Color.LightGreen, 
                 Color.Black, XMessageBoxButtons.OK, XMessageBoxIcon.Error);
XMessageBox.show("Information MessageBox with Yes and No buttons, BackColor " + 
                 "is LightPink and ForeColor is Black.", "Example", 
                 Color.LightPink, Color.Black, XMessageBoxButtons.YesNo, 
                 XMessageBoxIcon.Information);

现在,是时候检查我们的自定义消息框了。运行解决方案,单击按钮,然后查看结果

2.jpg

现在,我们遇到一个问题,它只显示一行。第二行中的单词“Black”没有显示(由于启用了自动换行,“Black”在第二行)。显然,问题在于高度设置。让我们找出设置高度的位置。然后,我们找到了 XmessageBox 方法,其中有

height = (TextBox1.Lines.Length * TextBox1.Font.Height) + 40 + 40;

…设置高度,在该行上设置一个断点,以便我们知道当前值。

关注点

再次运行,当编译器在断点处停止时,将鼠标悬停在 TextBox1.LinesLength 上(第一个值,它将用于设置高度),我们看到此属性返回“1”。但是,TextBox1 包含两行。这意味着,当启用自动换行时,Length 属性无法正常工作。因此,我们需要显式计算行数。为此,请添加一个类。现在,用此内容替换其所有文本

using System;
using System.Windows.Forms;
namespace Custom_Featured_MessageBox
{
    public class XTextBox : TextBox
    {
        public int LinesCount()
        {
            Message msg = Message.Create(this.Handle, 0xBA, 
                          IntPtr.Zero, IntPtr.Zero);
            base.DefWndProc(ref msg);
            return msg.Result.ToInt32();
        }     
    }
}

在上面的代码中,TextBox 被继承,并添加了一个名为 LinesCount 的方法,该方法将返回确切的行长度,即使启用了自动换行。在此方法中,我们向基类的默认窗口过程发送一条消息作为引用。就是这样。

将默认 TextBox 替换为一个新 TextBox,并将 TextBox1.Lines.Length 替换为 TextBox1.LinesCount()。现在,替换后的行将看起来像

height = (TextBox1.LinesCount() * TextBox1.Font.Height) + 40 + 40;

现在,运行,是的!它正在工作……!!!

我们还可以添加自己的图像作为图标。为此

  1. 将图像添加到 Resources 中。
  2. XMessageBoxIcon 枚举中添加名称(任意名称)。
  3. 展开 SetIcon 方法。

例如,如果我们想添加一个“Delete”图像作为图标,只需将“Delete”图像添加到 Resources 中,然后展开 XMessageBoxIcon 枚举

public enum XMessageBoxIcon
{ Error, Question, Warning, Information, Delete, }

同样展开“SetIcon

void SetIcon(XMessageBoxIcon icon)
{ 
.
.
.
.
    else if (icon == XMessageBoxIcon.Delete)
        pictureBox1.BackgroundImage = 
          Custom_Featured_MessageBox.Properties.Resources.Delete;
}

现在,调用带有该图标的 XmessageBox

XMessageBox.show("Delete MessageBox with Yes, No and " + 
                 "Cancel buttons, BackColor is Control and ForeColor is Black.", 
                 "Example", XMessageBoxButtons.YesNoCancel, 
                 XMessageBoxIcon.Delete);

最后,我们得到了一个消息框,它可以做我们想要的任何事情。请给这篇文章评分,前提是您已经从头到尾读完了它。

© . All rights reserved.