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

创建自定义消息框第 2 部分

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.76/5 (18投票s)

2007 年 7 月 23 日

CPOL

10分钟阅读

viewsIcon

306783

downloadIcon

3315

如何创建带有按钮和图标的自定义消息框。

在 C# 中创建自定义消息框:第 2 部分

下载 CSharp_SampleMessageBox2.zip - 46.4 KB

引言


本文是“在 C# 中创建自定义消息框”的第 2 部分。在第 1 部分中,我简要解释了如何创建一个简单的自定义消息框,它由“确定/取消”按钮组成。在本文中,我将进一步解释如何添加更多按钮,例如“中止/重试/忽略”,以及如何显示图标以及针对不同类型消息的不同蜂鸣声。

背景

首先,简要回顾一下我的第一篇文章“在 C# 中创建自定义消息框”。MessageBox 中按钮背后的技术是为每个在 MessageBox 上单击的按钮返回一个字符串 ID。MessageBox 只有两个按钮(确定/取消),因此 ShowBox() 方法将返回字符串 1 或 2。通过使用返回的字符串值,我可以使用 if 语句来检查单击了哪个按钮。下面是我的上一篇 MessageBox 文章中的“如何使用 MessageBox”代码。

清单 1.0

 

string btnClicked = MyMessageBox.ShowBox("Do you want to exit");

if (btnClicked == "1")
{
//用户单击了“确定”按钮。执行一些处理
}
else
{
//用户单击了“取消”按钮。执行一些处理。
}
 

 

上面的代码有一个问题,那就是我们如何知道存储在 btnClicked 变量中的返回字符串值 1 对应于“确定”按钮。答案是,我们不知道。如果 MessageBox 有更多按钮,每个按钮都分配了一个字符串 ID,那么我们就会搞不清哪个数字对应哪个按钮。为了解决这个问题,我们需要研究 Windows C# MessageBox 如何返回按钮单击。

下面的代码演示了如何显示带有“是/否”按钮的 C# Windows MessageBox。

列表 1.1

 

MessageBox.Show("消息框中的示例数据", "消息框标题", MessageBoxButtons.YesNo);

 

请注意粗体突出显示的代码。MessageBoxButtons 是一个枚举。枚举是一种由一组命名常量(称为枚举器列表)组成的独特类型。枚举器列表中的每个枚举器都有一个值。默认情况下,第一个枚举器的值为 0,第二个枚举器的值为 1,依此类推。值可以根据您的需要进行更改。此外,默认情况下,枚举元素的基础类型是 int。此类型可以更改为其他类型(char 除外)。

知道了这一点,我们可以使用 MessageBoxButtons 枚举来设置我们希望在自定义 MessageBox 上显示的按钮。在我们的 MessageBox 类中,我们可以使用“if 语句”检查所选枚举器的值。例如,如果所选枚举器是 YesNo,那么我们可以通过在运行时将按钮添加到面板来显示 Yes/NO 按钮。

下面的代码创建了一个 MessageBox,此代码与清单 1.1 中的代码相同,不同之处在于我们使用的是自定义 MessageBox 类 - CYMessageBox

列表 1.2

 

CYMessageBox.Show("您确定要退出吗?", "退出", MessageBoxButtons.YesNo);

 

在我们的 CYMessageBox 类中,我们需要检查选择了哪个枚举器。以下私有静态方法使用“if 语句”检查选择了哪个枚举器。

清单 1.3

 

static private void ButtonStatements( MessageBoxButtons MButtons)
{
if (MButtons == MessageBoxButtons.YesNo)
{
ShowNoButton();
ShowYesButton();
}
}

 

ButtonStatements() 方法在其参数中接受一个枚举器。然后检查该枚举器以查看选择了哪个枚举器。在清单 1.2 中,我们选择了 YesNo 枚举器。清单 1.3 中的代码将检查枚举器值并发现其为 true。然后它将执行 ShowNoButton()ShowYesButton() 方法。这两个方法负责创建 Yes 和 No 按钮并将它们添加到 MessageBox 上的 FlowLayoutPanel。每个按钮的创建都放在自己的方法中。这允许我们在需要时重用这些方法。例如,如果我们在清单 1.4 中列出了以下方法,我们可以混合搭配我们需要的按钮。

清单 1.4

 

ShowNoButton();
ShowYesButton();
ShowCancelButton();
ShowOKButton();

 

我们可以使用 ShowYesButton()ShowOKButton() 方法在 MessageBox 上显示 Yes 和 OK 按钮。或者使用 ShowNoButton()ShowCancelButton() 方法在 MessageBox 上显示 No 和 Cancel 按钮。当然,在给定的两个示例中,我们都不会这样做,因为在 MessageBox 上有 Yes/OK 和 No/Cancel 按钮是没有意义的。正确的组合应该是 ShowYesButton()ShowNOButton() 来显示 Yes/No 按钮,ShowOKButton()ShowCancelButton() 来显示 OK/Cancel 按钮。使用这种方法,我们可以在需要时添加其他按钮,例如“帮助”按钮或“在线”按钮。让我们看看按钮方法后面的代码。清单 1.5 中的以下代码是 ShowYesButton() 方法的代码。

清单 1.5

 

static private void ShowYesButton()
{
btnYes = new Button();
btnYes.Text = "Yes";
btnYes.Size = new System.Drawing.Size(80, 25);
btnYes.BackColor = System.Drawing.Color.FromArgb(255, 255, 255);
btnYes.< = new < ("Tahoma", 8, < Style.Regular);
btnYes.Click += new EventHandler(btnYes_Click);
flpButtons.Controls.Add(btnYes);
}

 

此方法只是创建 Yes 按钮。btnYes 按钮在类中声明。创建按钮后,将其添加到 flpButtons 面板。这是一个 FlowLayoutPanel。

到目前为止,我们知道我们可以使用 MessageBoxButtons 枚举来显示所需的按钮。这是一个简单的案例,使用“if 语句”来确定选择了哪个枚举器并显示相应的按钮。但我们还没有解决如何在不返回字符串 ID(例如按钮 OK 为 1,取消按钮为 2)的情况下确定单击了哪个按钮的问题。

我们需要看看 Windows C# MessageBox 类如何返回 MessageBox 上单击的按钮。下面清单 1.6 中的代码显示了一个带有 Yes/No 按钮的 MessageBox。

清单 1.6

 

DialogResult button = MessageBox.Show("消息框中的示例数据", "消息框标题", MessageBoxButtons.YesNo);

if (button == DialogResult.Yes)
{
MessageBox.Show("单击了 Yes 按钮");
}

if (button == DialogResult.No)
{
MessageBox.Show("单击了 No 按钮");
}

 

请注意粗体突出显示的代码。DialogResult 也是一个枚举。Show() 方法返回一个值。此值是一个枚举器。如果 Show() 方法的返回值评估为 Yes,则会显示一个 MessageBox,其中显示“单击了 Yes 按钮”。如果它评估为 No,则会显示一个 MessageBox,其中显示“单击了 No 按钮”。DialogResult 枚举在清单 1.7 中包含以下枚举器。

清单 1.7
表数据取自 http://msdn2.microsoft.com/en-us/library/system.windows.forms.DialogResult.aspx

成员名称描述
Abort对话框返回值是 Abort(通常由标有 Abort 的按钮发送)。
取消对话框返回值是 Cancel(通常由标有 Cancel 的按钮发送)。
Ignore对话框返回值是 Ignore(通常由标有 Ignore 的按钮发送)。
对话框返回值是 No(通常由标有 No 的按钮发送)。
对话框未返回任何内容。这意味着模态对话框继续运行。
好的对话框返回值是 OK(通常由标有 OK 的按钮发送)。
重试对话框返回值是 Retry(通常由标有 Retry 的按钮发送)。
对话框返回值是 Yes(通常由标有 Yes 的按钮发送)。

所以现在我们知道 C# MessageBox 类返回一个枚举值,然后使用 DialogResult 在“if 语句”中进行评估。这意味着我们需要从重载的 Show() 方法返回一个 DialogResult 值。但是我们怎么知道这个值是什么呢?我们自定义 MessageBox 上显示的每个按钮都有一个 Click 事件。当单击一个按钮时,我们在 DialogResult 的一个实例上设置值(枚举器)。该实例在 CYMessageBox 类中声明。Yes 按钮的代码如下面清单 1.8 所示。

清单 1.8

 

static void btnYes_Click(object sender, EventArgs e)
{
CYReturnButton = DialogResult.Yes;
newMessageBox.Dispose();
}

 

当单击 Yes 按钮时,CYReturnButton 的值(它是 DialogResult 的一个实例)设置为“Yes”。我们重载的 Show() 方法简单地返回此值。然后使用 Dispose() 方法处置 MessageBox。下面是清单 1.9 中 Show() 方法的代码。

清单 1.9

 

static public DialogResult Show(string Message, string Title, MessageBoxButtons MButtons)
{
BuildMessageBox(Title); // BuildMessageBox 方法,负责创建 MessageBox
frmTitle.Text = Title; // 设置 MessageBox 的标题
frmMessage.Text = Message; // 设置 MessageBox 的文本
ButtonStatements(MButtons); // ButtonStatements 方法负责显示适当的按钮
newMessageBox.ShowDialog(); // 将 MessageBox 显示为对话框
return CYReturnButton; // 将按钮单击作为枚举器返回
}

 

我提供了示例 MessageBox 的链接。为了更好地理解,请查看代码。示例代码不使用 MessageBoxButtons 枚举。我声明了自己的枚举,名为 CYButtons

显示图标

图标也使用枚举显示。我们可以使用“if 语句”来确定选择了哪个图标。我不会解释如何做到这一点,因为这个概念与显示按钮类似。我将解释的是图标的使用。起初,我考虑使用图像作为图标。我没有立即采纳这个想法,而是决定研究使用系统图标。我知道 Shell32.dll 中有图标,但我需要一种方法来获取它们并在我的自定义 MessageBox 中使用它们。幸运的是,我在互联网上找到了一些非托管 C# 代码,它完全符合我的要求。下面清单 2.0 显示了用于从 Shell32.dll 中提取图标的代码。

列表 2.0

 

[DllImport("Shell32.dll")]
public extern static int ExtractIconEx(string libName, int iconIndex, intPtr[] largeIcon, intPtr[] smallIcon, int nIcons);

private intPtr[] largeIcon;
private intPtr[] smallIcon;
private Icon frmIcon;
private PictureBox pIcon;

.............................................................

largeIcon = new intPtr[250];
smallIcon = new intPtr[250];

ExtractIconEx("shell32.dll", 0, largeIcon, smallIcon, 250);

frmIcon = Icon.FromHandle(largeIcon[23]);

Image imageIcon = new Bitmap(frmIcon.ToBitmap(), 38, 38);
pIcon = new PictureBox();
pIcon.Image = imageIcon;

 

上面代码中最重要的部分是粗体字。这获取了存储在“largeIcon”中给定索引位置的图标。您可以更改值以获取其他图标。

消息框蜂鸣声

最后,我们来到 MessageBox 蜂鸣声。如果您没有注意到,标准 MessageBox 在显示时会发出蜂鸣声。它针对不同类型的 MessageBox 有不同的蜂鸣声。例如,普通 MessageBox 有一种蜂鸣声,警告 MessageBox 有另一种蜂鸣声。现在我们知道了,问题是如何发出不同的蜂鸣声?我们再次使用非托管代码。清单 2.1 显示了发出蜂鸣声的代码。

清单 2.1

 

[DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern bool MessageBeep(uint type);

..................................................
MessageBeep(0); //标准蜂鸣声。
MessageBeep(30); //警告蜂鸣声。

 

本教程到此结束。我希望您喜欢阅读它。如果我有什么地方解释不正确,请留言,我会尽力纠正。您可以下载源代码并尝试使用代码。

关注点

我还没有找到一种方法可以根据消息文本扩展消息框。示例 MessageBox 代码不会像 Windows MessageBox 那样扩展消息框。

© . All rights reserved.