I have a form with the property "MDI container" set to true that opens MDI children when pressing Labels on a MenuStrip, but I have two problems:
The first one is that once I open an MDI Child I can not open another one; I press different labels on the same MenuStrip that I pressed to open the current MDI child and nothing happens.
The second problem is that I can not open an MDI child form from another MDI child form from code.
Following this paragraph, I will show the relevant parts of my code and some things that I have tried (with no solutions)
//Event of the MenuStrip that opens an MDI child (homePage or sellProduct) from the MDI container
HomePage homePage = null;
SellProduct sellProduct = null;
private void HomeToolStripMenuItem_Click(object sender, EventArgs e)
{
if (homePage == null)
{
homePage = new HomePage();
homePage.TopLevel = false;
homePage.MdiParent = this;
}
homePage.Show();
}
private void ToolStripSellPtoduct_click(object sender, EventArgs e)
{
if (sellProduct == null)
{
sellProduct = new SellProduct();
sellProduct.TopLevel = false;
sellProduct.MdiParent = this;
}
sellProduct.Show();
}
I have tried to copy this in a child form but it does not work. something that may be important is that when I load the MDI container I also load the first MDI child:
private void MainPage_Load(object sender, EventArgs e)
{
if (homePage == null)
{
homePage = new HomePage();
homePage.TopLevel = false;
homePage.MdiParent = this;
}
homePage.Show();
}
And that is all the code I consider necesary for the first problem (I can not open a MDI child form from another using my MenuStrip). If you need anything from my code I will provide it.
In the second problem (I can not open an MDI child form from another from code) I am trying to open the MDI child form "HomePage" from the other one "SellProduct" when pressing a button located in the last one:
public partial class SellProduct : Form
{
public SellProduct()
{
InitializeComponent();
}
private void Button_Sale_Click(object sender, EventArgs e)
{
HomePage homePage = new HomePage();
homePage.show();
this.close();
}
}
}
}
The code above closes MDI form SellProduct showing the mdiparent (but it does not execute again the mdi parent, and the MenuStrip still does not work, is weird) and opens a MDI parent (where the MenuStrip actually works). So no, it does not open another mdi child, it just do weird stuffs.
And that is all, thank you for your time, every help is welcome, and hope you have a great day (: .
I have finally solved this, this is my solution:
Problem 1) Once I open an MDI Child I can not open another one; I press different labels on the same MenuStrip that I pressed to open the current MDI child and nothing happens.
Solution: The MDI child forms were not showing because I had to hide the one opened (from the MainPage) before showing another one.
Problem 2) I can not open an MDI child form from another MDI child form from code.
Solution: It is the same problem as the first one If the actual form displayed is not hidden a new one can not be shown, because of that you have to hide the current one, and then open the new one:
//In this case I want to show the HomePage
this.Hide();
HomePage homePage = new HomePage();
homePage.Show();
I have 2 Forms and i want them to be inserted into a form with a tabcontrol. I have read this question about adding forms to tabcontrols and Form1 is successfully inserted into the tabcontrol. Form2 is also inserted but the content of the form is not showing.
This is my code:
private FrmMainForm trackIT = new FrmMainForm();
private MainForm customer = new MainForm();
private void TrackITForm_Load(object sender, EventArgs e)
{
AddNewForm(trackIT, trackitTab);
AddNewForm(customer, customerTab);
}
public void AddNewForm(Form form, TabPage tab)
{
form.WindowState = FormWindowState.Maximized;
form.TopLevel = false;
form.Parent = tab;
form.Visible = true;
}
I also have set my parent Form's IsMDIContainer property to true.
What can be the issue here?
I also have set my parent Form's IsMDIContainer property to true : Don't do that. You're not doing MDI.
In AddNewForm(), set the WindowState property after all the others.
I think (not 100% sure) that Visble=true is not enough, call form.Show() instead. Do it after setting the WindowState and especially the Parent.
Check the forms for conflicting properties in the designer code and FormLoad.
Consider using UserControls instead of Forms. They are meant to be embedded.
Basically I am having two problems with C#.NET MDI. You can download VS2010 solution which reproduces bugs here.
1) When programmatically hiding and showing again a maximized child form, it is not maximized properly again and becomes neither maximized or in normal state.
childForm = new Form();
childForm.Text = "Child Form";
childForm.MdiParent = this;
...
private void showButton_Click(object sender, EventArgs e)
{
childForm.Visible = true;
}
...
private void hideButton_Click(object sender, EventArgs e)
{
childForm.Visible = false;
}
When child form is maximized, then programicaly hidden and shown again, it becomes something like this (please notice the menu bar - child form's control box appears, but child form is not maximized):
At this stage, child form cannot be moved around. However, I found a workaround for that, simply by showing and hiding a dummy child form, which forces the actual child form to become properly maximized. But this makes MDI area to flicker. Tried Invalidate, Refresh, Update methods, but they don't help. Maybe there are other workarounds to overcome this bug and not to make MDI area flicker with dummy child form?
private void workaround1Button_Click(object sender, EventArgs e)
{
dummyForm.Visible = true;
dummyForm.Visible = false;
}
2) When child form is maximized, the icon of the child form is displayed on menu bar. However, if you have to change the icon while the child form is maximized, the icon on the menu bar is not being refreshed (see the image above). I found a workaround for that too, which basically hides and shows menu bar. Icon gets refreshed, but it makes everything below menu bar to flicker. Tried Invalidate, Refresh, Update methods, but they don't help. Is there any other way to make menu bar to refresh the child form's icon?
private void workaround2Button_Click(object sender, EventArgs e)
{
menuStrip.Visible = false;
menuStrip.Visible = true;
}
Also I noticed that when parent form is in normal window state mode (not maximized) and you change the width or height of the form by 1 pixel, child form becomes maximized as it should be and child form's icon on menu bar gets refreshed properly and you don't need other workaround I described above. If I change the size of the form programicaly, form flickers by 1 pixel and I cannot do that, when parent form is maximized. Is there any way how I could invoke the repaint/refresh functionality which is called when you resize a form and which makes child form become maximized properly and the icon on the menu bar refreshed?
There's a bug in the implementation of the internal MdiControlStrip class, the control that displays the icon and the min/max/restore glyphs in the parent window. I haven't characterized it as yet, the code isn't that easy. A classic side effect of the bug is that the glyphs get doubled up, you found some other side-effects. The fix is simple though, delay creating the child windows until after the constructor is completed. Like this:
public MainForm()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e) {
childForm = new Form();
childForm.Text = "Child Form";
childForm.MdiParent = this;
dummyForm = new Form();
dummyForm.MdiParent = this;
dummyForm.WindowState = FormWindowState.Maximized;
base.OnLoad(e);
}
Have you tired using Hide/Show instead of setting visible to true/false?
Try:
private void showButton_Click(object sender, EventArgs e)
{
childForm.Show();
}
private void hideButton_Click(object sender, EventArgs e)
{
childForm.Hide();
}
How about this workaround?
private void showButton_Click(object sender, EventArgs e)
{
childForm.Visible = true;
childForm.WindowState = (FormWindowState)childForm.Tag;
}
private void hideButton_Click(object sender, EventArgs e)
{
childForm.Visible = false;
childForm.Tag = childForm.WindowState;
childForm.WindowState = FormWindowState.Normal;
}
UPDATE
I just gave you the idea how you could do. A better solution using the same idea as above would be a new base form which saves the windows state. See below. Derive your forms from FixedForm instead of Form:
public partial class FixedForm : Form
{
private FormWindowState lastWindowState;
public FixedForm()
{
InitializeComponent();
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible)
{
WindowState = lastWindowState;
}
else
{
lastWindowState = WindowState;
WindowState = FormWindowState.Normal;
}
}
}
Found a way how to come around those bugs.
First of all you need to suspend painting for a form and its children. I found a very helpful thread here, which describes how to do it.
After suspending painting, you need call UpdateBounds method of the control and increase ClientRectangle Width or Height by one and then decrease it back to the same value it was before. This invokes layout functionality which makes everything to update/repaint. Last step is to enable painting. Not very nice solution I guess, but it works.
StopDrawing();
UpdateBounds(Location.X, Location.Y, Width, Height, ClientRectangle.Width, ClientRectangle.Height + 1);
UpdateBounds(Location.X, Location.Y, Width, Height, ClientRectangle.Width, ClientRectangle.Height - 1);
StartDrawing();
I find suspending painting very helpful not only for working around those two bugs, but also in general to make GUI work more smoothly. I guess this can help to remove any kind of flickering. However, this solution requires P/Invokes, which should be avoided in general.
Why not just manually reset required icon in menuStrip items, after the creation of the window:
menuStripMain.Items[0].Image = null;
This one has really got me stumped. I have certain forms that are being instantiated. When I instantiate a form i make it a child of the mdi form by
form1.MdiParent = this;
I have set the MDIWindowListITem property of my menustrip to a toolstripmenuitem
However this toolstripmenuitem does not show the mdi child form when it is instantiated
Does any one have any ideas on this?
Any inputs/ leads / hints would be most welcome. I am using .net framework 3.5
Regards
,
You have to write your code so that it is added manually I believe.
See the example here for pointers:
MSDN help on ToolStripPanel
Edit
You're right ignore my previous entry here's the code for a very simple MDI app that appears to do what your after.
It is just two blank forms. Form1 has IsMDIContainer=true. It also has menuStrip1, which contains two items "new" (newToolStripMenuItem) and "windows" (windowsToolStripMenuItem). Clicking new will open a new child window. I have set the MDIWindowListItem of menuStrip1 to windowsMenuStripItem. When a new child window is opened clicking on windowsMenuStripItem produces a drop down that shows all windows open.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private int count;
public Form1()
{
InitializeComponent();
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
count++;
//Set a window title text as this is what is shown in the window list.
Form2 newForm = new Form2() { Text = string.Format("Window {0}", count) };
newForm.MdiParent = this;
newForm.Show();//<--- this needed to show window in list.
}
}
}
There is no code in Form2.
The child windows only show below windowMenuStripItem once Form.Show() has been called.
Without this they do not show in the list.
How can I show a child form within a mdi container form which its windowstate= maximized ?
when I put these below lines of code when my child form is loading (by clicking on a menu Item of my Main form), the child form loses its parent position and does not show within its parent form.
private void mnuUnit_Click(object sender, EventArgs e)
{
frmUnit frm = new frmUnit();
frm.MdiParent = this;
frm.WindowState = FormWindowState.Maximized;
frm.Show();
}
Did you forget to paste your code?
To show an MDI child form as maximized, you do the following:
// This is a method on the MDI parent (IsMdiContainer = true)
private void Button1_Click(object sender, EventArgs e)
{
var myForm = new MyCustomForm();
myForm.MdiParent = this;
myForm.WindowState = FormWindowState.Maximized;
myForm.Show();
}
You can set the dock style to fill and before calling show, use
myForm.BringToFront();