在所有窗体顶部显示消息框,设置位置和/或颜色。

6

我有两个窗体并将其中一个窗体的TopMost属性设置为true。在程序运行期间,我在某处显示一个MessageBox,但由于TopMost设置为true,当MessageBox弹出时,它会显示在最顶层的窗体下面,所以我看不到它。

  1. 有没有办法让我的一个窗体始终保持在顶部,但是当MessageBox弹出时,使其显示在该特定窗体的顶部?

  2. 是否可以为MessageBox指定位置,使其不在中央,而是例如在屏幕下方低处显示?

  3. 假设我有一个橙色的窗体,我能否为该特定应用程序设置一个粉色的MessageBox。我的意思是,我不是指播放Windows颜色属性。(我不希望所有的消息框都是粉色的。)


如果你不想让所有的消息框都是粉色的,那么你也不应该希望你的消息框是粉色的。标准系统颜色存在的原因是有道理的。 - Cody Gray
@CodyGray:你看过第三点了吗?她想让那个特别重要的消息得到突出显示... - quetzalcoatl
7个回答

11

我使用这个。

MessageBox.Show(
                "message",
                "title",
                MessageBoxButtons.OK,
                messageBoxIcon,
                MessageBoxDefaultButton.Button1,
                (MessageBoxOptions)0x40000); // this set TopMost

1
(MessageBoxOptions)0x40000与MessageBoxOptions.ServiceNotification执行相同的操作。 - Sasha Bond
1
ServiceNotification = 枚举值2097152。 它的十六进制表示为0x200000。 - Kim Ki Won

9

1) MessageBox.Show方法有一个重载,可以接受Window类型的第一个参数。如果您使用该重载而不是仅使用Show(string),例如:

class MyForm : Form {
    void method(){
       MessageBox.Show(this, "blablablablabla");
    }
}

如果以'modal'模式显示MessageBox,它将准确地出现在该窗体的顶部。现在只需确保通过该顶部窗体即可完成。副作用是'modal'模式将导致Messagebox阻止原始窗口,直到消息被解除。

2) 不,这不可能直接实现。但是,您可以通过.Net进行操作,并获得一个指向消息框的“句柄”,然后通过P/Invoke移动窗口到一些WinApi函数,但我建议您不要这样做。

3) 不,使用MessageBoxes无法实现该目标。

因为MsgBox旨在保持简单,所以您想在(2)和(3)中实现的内容是不可能的。要获取这些内容,您必须编写自己的小型窗体,该窗体将充当消息框,并呈现该窗体而不是消息框。该窗体将能够具有任何样式、任何位置和任何您喜欢的行为方式。


请再次阅读问题,并测试您的代码。在这种情况下,它将无法工作。 - Saber Amani
感谢您提供有关问题2和3的信息和替代方法,我非常感激。至于第一部分,我已经写好了。 - modest and cute girl
私有的 void pictureBox1_Click(object sender, EventArgs e) { 如果 (MessageBox.Show(this, "程序将被关闭,您确定吗?", "!!!警告!!!", MessageBoxButtons.YesNo) == DialogResult.Yes) { Application.Exit(); } } // 但是这并没有起作用 - modest and cute girl
顺便提一下,那个关闭图片图像(pictureBox1)在form1上,而在form1上面我有一个topmost属性设置为true的form2。当我单击关闭图片时,消息框弹出,但它会被置于topmost的form2下面。 - modest and cute girl
@quetzalcoatl的MessageBox第二个重载函数解决了问题,正如quetzalcoatl所说。所以我非常感谢他的教导和展示。如果我写上MessageBox.Show(frm1, "BLARGH"); // 那么消息会显示在frm1的顶部,无论它的topmost设置为true还是false。如果我们写frm2,则它会显示在frm2的顶部。再次感谢quetzalcoatl。 - modest and cute girl

8
为了在应用程序的所有其他窗体(包括那些已设置 TopMost 的窗体)上方显示一个 MessageBox,您可以使用带有类型为 MessageBoxOptions 的参数的 Show() 方法重载,并将 MessageBoxOptions.ServiceNotification 作为该参数传递。保留html标签。
DialogResult result = MessageBox.Show("Configuration file was corrupted.\n\nDo you want to reset it to default and lose all configurations?", "Config File Corrupted", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, MessageBoxOptions.ServiceNotification);

5
一个简单的实现顶部 MessageBox 的方法如下所示:
using (var dummy = new Form() { TopMost = true })
{
    MessageBox.Show(dummy, text, title);
}

您不必真正显示虚拟表单。


1

我认为在 .Net 中没有内置的功能来实现这一点,但我建议您保留您的 TopMost 窗体的引用,并在显示每个消息之前更改它,类似于以下内容:

    public static void ShowMessage(string message)
    {
        Component.InstanceOfTopMost.TopMost = false;
        MessageBox.Show(message);
        Component.InstanceOfTopMost.TopMost = true;
    }

Component 是一个静态类,它保存了你的窗体的引用,该窗体应该是 TopMost。使用这个静态类的原因是你可能想在多个地方使用该窗体,这样你就可以轻松地访问你的窗体。 这是一个简单的方法,你可以根据自己的需求进行更改。

更新:

        public class Component
        {
            public static Form2 InstanceOfTopMost { get; set; }
        }

Component只是一个名称,给它另一个名称,因为还有另一个名为Component的.Net类。

        var frm = new Form2();
        Component.InstanceOfTopMost = frm;
        frm.Show();

希望这有所帮助。

私有的 void pictureBox1_Click(object sender, EventArgs e) { Component.InstanceOfTopMost.TopMost = false;if (MessageBox.Show("程序将被关闭,您确定吗?", "!!!警告!!!", MessageBoxButtons.YesNo) == DialogResult.Yes) { Application.Exit(); } Component.InstanceOfTopMost.TopMost = true;} - modest and cute girl
你遇到了什么错误或异常?你是否填充了 TopMost 表单的实例? - Saber Amani
那个关闭图片(pictureBox1)位于form1上方,而在该form上方我有一个topmost属性设置为true的form2。当我单击关闭图片时,消息框弹出,但它会被置于topmost的form2下面。 - modest and cute girl
你没有回答我的问题,你在 Component 类中填充了 Form2 的实例吗? - Saber Amani
IDE在InstanceOfTopMost这个单词下划了红线,并显示“System.ComponentModel.Component”不包含“InstanceOfTopMost”的定义。 - modest and cute girl
显示剩余6条评论

1

@Saber Amani:为什么这样?看,它只是有效的:

    using System.Windows.Forms;

    namespace ReusingUserControlsSample
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, System.EventArgs e)
            {
                Form1 second = new Form1();
                second.TopMost = true;
                second.Show();

                MessageBox.Show(second, "BLARGH");
            }

            private void InitializeComponent()
            {
                this.button1 = new System.Windows.Forms.Button();
                this.SuspendLayout();
                this.button1.Location = new System.Drawing.Point(178, 201);
                this.button1.Name = "button1";
                this.button1.Size = new System.Drawing.Size(75, 23);
                this.button1.TabIndex = 0;
                this.button1.Text = "button1";
                this.button1.UseVisualStyleBackColor = true;
                this.button1.Click += new System.EventHandler(this.button1_Click);
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(284, 264);
                this.Controls.Add(this.button1);
                this.Name = "Form1";
                this.Text = "Form1";
                this.ResumeLayout(false);

            }

            private System.Windows.Forms.Button button1;
        }
    }

消息框已正确显示在第二个窗体上,该窗体是TopMost。唯一的“问题”是要知道哪个窗体是最顶层的。


大家好,现在已经很晚了,已经是凌晨3点40分了,我要去睡觉了。我会检查你们的答案并尝试它们,然后再回来。但在我离开之前,我真的想说我尊重你们所有人的知识和羡慕你们。我很高兴人们在这里进行头脑风暴并试图证明。我希望我也能在很短的时间内成为专家。感谢Quetzalcoat和Saber的帮助。 - modest and cute girl

0
https://dev59.com/EF0b5IYBdhLWcg3wUP4X
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox

using System.Runtime.InteropServices;
//...
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
public static extern int MessageBox(IntPtr h, string m, string c, uint type);
const uint ICONERROR = 16;
const uint ICONWARNING = 48;
const uint ICONINFORMATION = 64;
const uint MB_TOPMOST = 262144;

//...
MessageBox((IntPtr)0, "Started" + DateTime.Now, "Log", ICONINFORMATION | MB_TOPMOST);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接