Reputation: 17444
If I programatically minimize the application's form while a modal dialog is open, that modal dialog gets closed.
However, if I programatically minimize the application's form while a MessageBox is open, the MessageBox is not closed (i.e. when I restore the application to normal window state, the message box is still showing).
Here's my sample code demonstrating the difference:
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();
}
}
Question:
Is there a way to get the Form to behave like the MessageBox?
Upvotes: 5
Views: 3670
Reputation: 3017
If you set
Visible = true;
on the modal form immediately after programmatically minimizing the owner from, the modal form does not get killed by the OS.
So
ownerForm.WindowState = FormWindowState.Minimized;
will kill the modal form. But
ownerForm.WindowState = FormWindowState.Minimized;
modalForm.Visible = true;
will not kill it.
Upvotes: 0
Reputation: 720
You can try something like this:
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();
}
}
}
}
Please note that this is somewhat an hack, I'm not totally sure about consequences. Criticism is acceptable :)
Upvotes: 0
Reputation: 32561
First, declare the Form2
form variable outside the method's scope, so it could be reachable from the timer1_tick
method. Then, when the Timer
ticks, minimize the main form, but show the modal dialog and then minimize it.
Try this:
Form2 form2;
private void timer1_Tick(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
form2.Show();
form2.WindowState = FormWindowState.Minimized;
timer1.Stop();
}
Upvotes: 1
Reputation: 941465
What you are seeing is the side-effect of countermeasures built in to Winforms to deal with dialog usability problems, countermeasures that the MessageBox() function doesn't have. They were probably more relevant to Windows 98, originally an important target operating system for Winforms, too long ago for me to remember accurately.
An important usability problem is what happens when you show a dialog and it gets minimized. A dialog disables all other windows in the app so you can no longer activate them. The dialog should have its ShowInTaskbar property set to false. The user now has a problem, there is no simple way to get back to the dialog. Nothing to click on.
Winforms avoids this trap by automatically closing the dialog. As you can tell, MessageBox doesn't do this. It can not reasonably do this either, it doesn't have a good way to return a "dialog was canceled" status code.
Notable is that this trap still partially exists. On my Win8 machine, I can click the disabled form's taskbar button and get it to move back in the foreground. But that activates the disabled form instead of the message box. Major UI blooper there and nasty if the message box is behind that form.
So to answer your question: no. Feature, not a bug.
Upvotes: 9
Reputation: 396
Matt,
Try changing:
form2.ShowDialog();
to
form2.Show(this);
Is this the behavior you are looking for?
Upvotes: 0