4

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

但是,如果我在 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();
        }
    }

问题:

有没有办法让表单表现得像 MessageBox?

4

5 回答 5

8

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

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

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

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

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

于 2013-01-25T00:11:59.443 回答
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();
}
于 2013-01-25T07:50:39.853 回答
0

如果你设置

Visible = true;

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

所以

ownerForm.WindowState = FormWindowState.Minimized;

将杀死模态形式。但

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

不会杀死它。

于 2014-04-07T02:16:43.823 回答
0

马特,

尝试改变:

form2.ShowDialog();

form2.Show(this);

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

于 2013-01-23T02:58:42.770 回答
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();
            }
        }
    }
}

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

于 2013-01-25T14:08:22.827 回答