最小化应用程序表单会导致模式窗体关闭,但不会关闭MessageBox

时间:2013-01-22 22:32:15

标签: c# winforms

如果我在打开模态对话框时以编程方式最小化应用程序的表单,则该模式对话框将被关闭。

但是,如果我在MessageBox打开时以编程方式最小化应用程序的表单,则MessageBox不会关闭(即当我将应用程序恢复到正常窗口状态时,消息框仍然显示)。

以下是我展示差异的示例代码:

    public partial class Form1 : Form
    {
        // ... 

        private void showMessageBoxBtn_Click(object sender, EventArgs e)
        {
            timer1.Start();

            // This MessageBox does *not* get closed when the WindowState of Form1 is set to minimized in timer1_Tick
            MessageBox.Show(this, "MessageBox");
        }

        private void formShowDialogBtn_Click(object sender, EventArgs e)
        {
            timer1.Start();

            // This form gets closed when the WindowState of Form1 is set to minimized in timer1_Tick
            Form2 form2 = new Form2();
            form2.ShowDialog(); 
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
            timer1.Stop();
        }
    }

问题:

有没有办法让Form表现得像MessageBox一样?

5 个答案:

答案 0 :(得分:6)

您所看到的是Winforms内置的对策的副作用,以处理对话可用性问题,MessageBox()函数没有的对策。它们可能与Windows 98更相关,Windows 98最初是Winforms的一个重要的目标操作系统,很久以前我才能准确记住。

一个重要的可用性问题是当你显示一个对话框并且它被最小化时会发生什么。一个对话框禁用应用程序中的所有其他窗口,因此您无法再激活它们。该对话框应将其ShowInTaskbar属性设置为false。用户现在遇到问题,没有简单的方法可以回到对话框。没有什么可点击的。

Winforms通过自动关闭对话框来避免此陷阱。如您所知,MessageBox不会这样做。它也不能合理地做到这一点,它没有一个好的方法来返回“对话框被取消”状态代码。

值得注意的是,此陷阱仍然部分存在。在我的Win8机器上,我可以单击禁用的表单的任务栏按钮,让它在前台移回。但是这会激活禁用的表单而不是消息框。如果消息框在该表单后面,那么主要的UI blooper和讨厌。

所以回答你的问题:不。功能,而不是错误。

答案 1 :(得分:1)

首先,在方法范围之外声明Form2表单变量,因此可以从timer1_tick方法访问它。然后,当Timer滴答时,最小化主窗体,但显示模态对话框然后将其最小化。

试试这个:

Form2 form2;

private void timer1_Tick(object sender, EventArgs e)
{
    WindowState = FormWindowState.Minimized;
    form2.Show();
    form2.WindowState = FormWindowState.Minimized;
    timer1.Stop();
}

答案 2 :(得分:0)

马特,

尝试更改:

form2.ShowDialog();

form2.Show(this);

这是您正在寻找的行为吗?

答案 3 :(得分:0)

您可以尝试这样的事情:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication37
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
        public static extern IntPtr GetParent(IntPtr hWnd);

        Form2 form2 = null;
        IntPtr parent = IntPtr.Zero;

        public Form1()
        {
            InitializeComponent();
        }

        private void formShowDialogBtn_Click(object sender, EventArgs e)
        {
            timer1.Start();

            // This form gets closed when the WindowState of Form1 is set to minimized in timer1_Tick
            form2 = new Form2();
            form2.ShowDialog();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
            timer1.Stop();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.parent = GetParent(form2.Handle);
                SetParent(form2.Handle, IntPtr.Zero);
                form2.Hide();
            }
            else
            {
                SetParent(form2.Handle, this.parent);
                form2.ShowDialog();
            }
        }
    }
}

请注意,这有点像黑客,我不完全确定后果。批评是可以接受的:)

答案 4 :(得分:0)

如果您设置

Visible = true;

在以编程方式最小化所有者之后的模态表单上,模态表单不会被操作系统杀死。

所以

ownerForm.WindowState = FormWindowState.Minimized;

会杀死模态表单。但

ownerForm.WindowState = FormWindowState.Minimized;
modalForm.Visible = true;

不会杀了它。