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






2.76/5 (18投票s)
如何创建带有按钮和图标的自定义消息框。
在 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 那样扩展消息框。