Howto create semi-modal popup form in MDI application

G

Guest

I'm creating an MDI application in C# 2.0.

I need to show a popup form (similar to a dialog) on an MDI child form, such
that the popup form is modal to the MDI child form, but without blocking
other MDI child forms and obviously without blocking the main application.

I know that I can't use Form.ShowDialog() as it disables all windows on the
thread, but I'm hoping there's a way to simulate the desired behavior. The
popup form has to be associated or parented to the MDI child form so that the
user can switch between the open child forms. More than one MDI child form
can show a popup form at the same time.

Hope someone out the has a suggestion...

Regards
Henrik Rasmussen
 
B

Bob Powell [MVP]

L

Linda Liu [MSFT]

Hi Henrik,

I agree with what Bob said that a form will either be modal or modeless. If
you want a form to be modal for one specific form and modeless for other
forms, you may do this by code.

The following is a sample. I create a Windows application project and add
four forms into the project. They're called Form1, Form2, Form3 and Form4
respectively. Form1 is the MDI parent form. Form2 and Form4 are MDI child
form. Form3 is the popup form for Form2. I add a button called button1 in
Form2. When the button1 is clicked, Form3 is shown. Below is the code in
Form1and Form2.

private void Form1_Load(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
Form4 frm4 = new Form4();
frm2.MdiParent = this;
frm4.MdiParent = this;
frm2.Show();
frm4.Show();
}

public partial class Form2 : Form
{
Form3 frm = null;
private void button1_Click(object sender, EventArgs e)
{
if (frm == null)
{
frm = new Form3();
this.frm.FormClosed += new
FormClosedEventHandler(frm_FormClosed);
}
frm.Owner = this.MdiParent;
frm.TopLevel = true;
frm.ShowInTaskbar = false;
frm.Show();
// disable Form2, so that it cannot get focus until Form3 is
closed
this.Enabled = false;
}

void frm_FormClosed(object sender, FormClosedEventArgs e)
{
frm.FormClosed -= new FormClosedEventHandler(frm_FormClosed);
frm = null;
// When Form3 is closed, enable Form2 again
this.Enabled = true;
}
}

Hope this helps. If the above sample is not what you want, please feel free
to let me know.


Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi Linda,

Thank you for your reply. Yes, this is quite close to what I want. I had
come up with something along the same lines, but it leaves a few problems:

1. The popup form (Form3 in your sample) stays on top, not just on top of
the parent (Form2) but also any other MDI childs (Form4). So in a situation
with many MDI child forms of which several has a popup form, the popup forms
will cover it all.

2. Keyboard navigation between MDI windows doesn't work when the parent
(Form1) is disabled. Clicking the disabled parent doesn't activate the popup,
but rather the other MDI child.

In the button click handler in the sample you set the popup form's Owner
property. What is achieved by that?

I'm considering using a borderless control for the popup form, and then use
the theme rendering classes to draw a fake window in stead. What do you think
of that?

That way the fake form will follow the MDI child as any other control on the
form, including minimizing with the parent and going behind other MDI child
forms.

Sincerely,
Henrik Rasmussen
 
L

Linda Liu [MSFT]

Hi Henrik,

Sorry for my delayed reply.

I set the Owner property of Form3 to make Form3 minimized when the owner
form is minimized and restored when the owner form is restored.

You have mentioned in your first message that you want to show a modal
popup form for an MDI child form, which means we couldn't select or
activate the MDI child form when the popup form is shown.

However, you said 'That way the fake form will follow the MDI child as any
other control on the form, including minimizing with the parent' in your
sencond message, which means we could activate the MDI child form when the
popup form is shown. I think the two requirements may be contradictory.

Based on my understanding, you want to show a popup form for each MDI child
form. When a popup form is shown, the corresponding MDI child form is
'disabled' but we could still move or minimize it. When we move the MDI
child form, the popup form follows the child form. When we minimize the MDI
child form, the popup form is minimized too. When we try to activate the
MDI child form, the popup form is activated actually.

I have modified my sample I provided in my first reply to meet the above
requirements. Below is the code in Form2.

public partial class Form2 : Form
{
Form3 frm = null;
public Form2()
{
InitializeComponent();
this.Activated += new EventHandler(Form2_Activated);
this.SizeChanged += new EventHandler(Form2_SizeChanged);
this.Move += new EventHandler(Form2_Move);
}

void Form2_Move(object sender, EventArgs e)
{
if (frm != null)
{
frm.Location = new Point(this.Location.X + 20,
this.Location.Y + 20);
}
}

void Form2_SizeChanged(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
if (frm != null)
{
frm.WindowState = FormWindowState.Minimized;
}
}
else
{
if (frm != null)
{
if (frm.WindowState == FormWindowState.Minimized)
frm.WindowState = FormWindowState.Normal;
}
}
}


void Form2_Activated(object sender, EventArgs e)
{
if (frm != null)
frm.Focus();
}

private void EnableControls(bool flag)
{
// add code to enable/disable all the controls in this form
}

private void button1_Click(object sender, EventArgs e)
{
if (frm == null)
{
frm = new Form3();
this.frm.FormClosed += new
FormClosedEventHandler(frm_FormClosed);
this.frm.SizeChanged += new EventHandler(frm_SizeChanged);
}

frm.MdiParent = this.MdiParent;
frm.TopMost = true;
frm.Show();
frm.Location = new Point(this.Location.X + 20, this.Location.Y
+ 20);
this.EnableControls(false);

}

void frm_FormClosed(object sender, FormClosedEventArgs e)
{
frm.FormClosed -= new FormClosedEventHandler(frm_FormClosed);
frm = null;
this.EnableControls(true);
}

void frm_SizeChanged(object sender, EventArgs e)
{
if (frm.WindowState == FormWindowState.Minimized)
this.WindowState = FormWindowState.Minimized;
else
this.WindowState = FormWindowState.Normal;
}
}

Except for the funtions I mention above, this sample also provides
functions that when the MDI child form is restored, the popup form is
restored, that when the popup form is minimized, the child form is
minimized, and that when the popup form is restored, the child form is
restored too.

Hope this helps.
If you have any concerns, please feel free to let me know.


Sincerely,
Linda Liu
Microsoft Online Community Support
 
G

Guest

Linda,

You're right in your assumptions, and I was a bit vague in my description.
I'll try to incorporate this into my application. I seems to work. Thank you,
for your help.

Kind regards
Henrik Rasmussen
 
G

Guest

I have found this post very helpful but having created the test application
using the code provided here I have found a small problem...

The steps to recreate it are as follows...

Run the application - Form2 and Form4 are displayed automatically.

Press the button on Form2 to show Form3 in its semi-modal state.

Move Forms 2,3 and 4 so they are all visible (not overlapping) to easily see
which has focus.

Give focus to Form4 (click anywhere on it).

Click anywhere on Form2 (except the window handle). Focus is redirected to
Form3 as expected.
Again Click anywhere on Form2 (except the window handle). This time focus
does not get redirected to Form3 - it remains with Form2. Why is this ?

Also If you click on the windowhandle of Form2 the focus does not get
redirected to Form3 even if it is the first time you give focus to Form2.


I would like to have a consistent behaviour where Form2 always gives focus
to Form3 while Form3 is open.

Can anyone else see this behaviour and if so can they explain what is
happening or how to get around it ?

Kind Regards

Lenster ;¬)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top