Panel changes it size in MdiContainer - c#

We're running into a small problem here which really annoys us. Let me quickly explain what we're doing:
We're creating a Windows Form, save it as .DLL and load it a MDIContainer. Seems fine, works fine, except that, if we're using a Panel as component in our Form, it changes the size.
Before:
After (in MDIContainer):
(NOTE THE PANEL!).
We're guessing that it's because of our Custom MDI Container. This is the code of our MDI Container:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace NAMESPACE.Forms
{
class MdiClientPanel : Panel
{
private Form mdiForm;
private MdiClient ctlClient = new MdiClient();
public MdiClientPanel()
{
this.ctlClient.BackColor = Color.LightGray;
base.Controls.Add(this.ctlClient);
}
public Form MdiForm
{
get
{
if (this.mdiForm == null)
{
this.mdiForm = new Form();
System.Reflection.FieldInfo field = typeof(Form).GetField("ctlClient", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
field.SetValue(this.mdiForm, this.ctlClient);
}
return this.mdiForm;
}
}
}
}
Is there any way we can fix this? Thanks for helping.
//Edit:
Added bounty, because we want to know why this is so. How you can reproduce it:
Copy our MDIClientPanel code inside a new class in a new project
Create a second form, put some Controls inside it.
Load the form inside the MDIClient Panel.
Compile and look how the Size of the second form is changing.
This can be fixed if you open the second form like this:
SecondForm Form = new SecondForm();
Form.MdiParent = this.MdiClientPanel.mdiForm;
Form.Size.Width += 35; //THIS PART WILL FIX
Form.Size.Height += 20; //THIS PART WILL FIX IT
Form.Show();
But there is no way this is the only solution is it's kinda fishy...

The reason why this is happening, is because the boundries of the panel are not set.
You should be able to over come this by one of the following ways:
1 - Dock the panel;
var x = new MdiClientPanel{Dock = DockStyle.Fill};
Controls.Add(x); //Add the control to the form
2 - Anchor the panel to all corners;
x.Anchor = AnchorStyles.Top;
x.Anchor = AnchorStyles.Right;
x.Anchor = AnchorStyles.Left;
x.Anchor = AnchorStyles.Bottom;
I was able to reproduce this error and correct it using the above method(s).
Anchoring (before):
Anchoring (after - resizing parent):
Dock (before):
Dock (after - resize parent):
Hope this helps.

You have a fixed width and height at design time, it somehow does not follow your form to resize itself.
normally what we do is always to use a table layout panel (if there are more than one visible controls on the same form) and for each control, set the Dock to DockStyle.Fill. if there is only one control in the form, set the control itself to fill in to the form or the parent control (such as a tableLayoutPanel), and then set the following at either Design or behind-code:
pnl.Dock = DockStyle.Fill;
if you do want to leave some pace beside some controls, use TableLayoutPanel to have extra columns/rows with width (either fixed or in percentage). and then place the controls (like your panel) inside the cell you choose and set dockstyle to fill.

Consider anchoring the panel in your form. This will ensure that the panel will have equal space around it, regardless of the size of its parent form. Generally I prefer this over DockStyle.Fill.
When using the form as an MDI child, you really want to delegate control over its size to its MDI container. Just make sure your MDI child handles it nicely.

Related

C# combobox does not display correctly inside splitcontainer

I have a form with a splitcontainer. One of the panels in the splitcontainer then loads a user control. This user control contains a combobox with the following properties changed from default:
DrowdownStyle=DrowDownList
FlatSyle=flat
Anchor=top,left,right
When the form and user control load, the combobox looks as expected:
However, if I resize the splitcontrol, it starts looking weird. If I increase the size of the panel that holds the control, this happens:
If i decrease the size of the splitter, it looks less weird, but still not how it is supposed to:
In either case, the combobox starts looking normal once I mouse over it.
Here is my code:
Main Form:
//Main form. Has a split container created from the toolbox
public partial class SampleForm:Form
{
public SampleForm()
{
InitializeComponent();
SampleControl cntrl = new SampleControl();
splitContainer1.Panel1.Controls.Add(cntrl);
splitContainer1.BorderStyle = BorderStyle.FixedSingle;
cntrl.Dock = DockStyle.Fill;
}
}
User Control:
//User control. Has a combobox created from toolbox. Options as described above
public partial class SampleControl : UserControl
{
public SampleControl()
{
InitializeComponent();
}
}
How can I fix this problem?
May be try to set dock to None . Also try to fix the margin for control
I know this is old, but was having the same problem and just in case someone finds themselves in the same predicament, answer below. Basically, create a new Class:
Imports System.Windows.Forms
Public Class MyComboBox
Inherits ComboBox
Protected Overrides Sub OnResize(e As EventArgs)
Me.Refresh()
End Sub
End Class
You can either drag this from your toolbox or add it in code. It will then auto redraw itself on resize of any parent controls.
Winforms is a bit like a sibling - flawed and deeply annoying sometimes - but you just gotta love it.

Show top most Child Form c#

How can I show topmost a button clicked child form in my parent form (with a tabcontrol which docked as fill)?
It always shows the form at the back of the tabcontrol of the parent form, I've even used:
frm.TopMost = true;
frm.BringToFront();
Still shows at the back.
What you want is not possible. MDI children of a control get shown on a control (which you can't directly select) called MdiClient, which is not transparent (and can't be) and by default, goes always to the back of other controls in the parent form.
So the only way to do this, would be getting the MdiClient over the controls in the parent form: this would do what you expect, but it would also hide the parent controls when there are no child forms displayed (since again, the MdiClient is not, and can't be transparent).
So the only reasonable way would be having a maximized child form with the TabControl, instead of having that TabControl directly on the parent.
Or you could have your TabControl only shown when there are no child windows. For that, make a timer in the parent form, and check this at every interval:
if(MdiChildren.Length > 0)
myTabControl.SendToBack();
else
myTabControl.SendToFront();
This will only work if the MDI children are always maximized: your TabControl will not be visible when there are any children (no matter if they cover it or not)
Update
As remarked in the comments, you can have "your own MDI", by having a host control (a Panel, for example) in the parent form and loading the child forms in that control:
var form = new ChildForm();
form.TopLevel = false;
form.Parent = myHostPanel;
form.Show();
This would show the form inside the panel (which you can locate and zorder where you want)... you lose all the MDI management though, and you'll have to keep track of your children (and take care of the forms' events if needed) yourself.
I'd not use this solution, it's pretty hacky and can get messy for big applications (unless you do a correct system)
As a summary
Since we're discussing these methods in the comments
You can hack your way to do what you want, but you'll come into all sorts of problems with any approach.
If I was you, I'd redesign my application so that what you want to achieve is not needed. If you can't do that, the only sane way would be just not having those controls in the parent form, have an always-maximized, non-closable MDI child form with those controls, and skip that window everytime you need to work in the MDI children collection.
Please explain what components of what frameworks you are using and what you have done so far. Without that information i suggest the following solution (untested).
In the "ButtonClick" event of your ParentForm do this:
ChildForm cf = new ChildForm();
cf.MdiParent = this;
cf.Show();
If this doesn't work you may add a
cf.Focus();
This question make me uncomfortable :). after a lot of testing, I can't really find a solution. neither BringToFront() Function nor SendToBack() Work Properly. maybe the following approach can help you. I use IntersectWith Function of Rectangle Class and test if form intersect with tabControl or not. if so change the tab control visibility to false otherwise true. take a look at the following code:
first make form declaration public at the mdi parent form:
public partial class MdiParentForm : Form
{
Form frm = new Form();
}
After that when you initialize your child form, add some handler to its locationChanged event, like this:
frm.MdiParent = this;
frm.LocationChanged += Frm_LocationChanged;
frm.Show();
And at the end, This is the handler:
private void Frm_LocationChanged(object sender, EventArgs e)
{
Rectangle tabControlRectangle = new Rectangle(tabControl1.Location, tabControl1.Size);
Rectangle childFormRectangle = new Rectangle(frm.Location, frm.Size);
if (tabControlRectangle.IntersectsWith(childFormRectangle))
{
tabControl1.Visible = false;
}
else
{
tabControl1.Visible = true;
}
}
Thanks to #Jcl, Problem with this is that the tab control will hide and show as long as any point of the child form touches its rectangle. Moving the child form around would be horrible :-)

Rendering issue with WPF controls inside ElementHost

I am having a WinForms control, inside that I have a TableLayoutPanel which holds multiple ElementHosts and each ElementHost contains a WPF control.
Everything works fine except when the size of controls is bigger then window and ScrollBar is there; when I scroll down, the controls get rendered distorted, like this -
On maximizing the window or re-sizing it, controls render properly
(reducing the size such that controls go out of visible area and then increase the size again to bring them back in visible area)
This doesn't happen with WinForms control in the same window just the WPF ones; any idea why this is happening and any solution for this?
this.Loaded += delegate
{
var source = PresentationSource.FromVisual(this);
var hwndTarget = source.CompositionTarget as HwndTarget;
if (hwndTarget != null)
{
hwndTarget.RenderMode = RenderMode.SoftwareOnly;
}
};
Try using that in the wpf control you are hosting. This is a known rendering issue of the the wpf controls that are hosted in win forms. Changing the rendering mode to software only will solve the problem.
I had a similar problem and solved forcing a refresh of the ElmenetHost in the scroll event of the TableLayoutPanel
Ok, this is gonna sound like total B.S. but it worked for me: in the Load event of your form, resize the form.
public class MyForm : Form
{
public MyForm()
{
Load += (o, e) => { Width -=1; Width +=1; };
}
}
After the form has been resized, I could not force a display issue.

Making a Toolstripcontainer panel work like an MDI parent

This is for C# and I am working in a Windows 7 environment with Visual Studio Express 2010.
I have an application where I have a toolstripcontainer dock set to fill so users can add toolstrips on any edge. The problem was that the toolstripcontainer has covered the that I want to use for holding sub-windows. The primary form containing the toolstripcontainer has been set as an mdi parent.
I found this article useful in getting the sub-windows into the container:
How to uses a ToolStripContainer whith Dock=Fill on a MDI parent?
However, sub-windows done in this way don't seem to behave as they should in the 'native' MDI environment. The boarders look as though the windows 7 Aero effect has been disabled and minimising the sub-window makes it disappear entirely.
Essentially I want an MDI area for sub-windows surrounded by toolstrip docking areas.
Thanks a lot for your help
Unfortunately, the ToolStripContainer control was not meant to work with an MDI form.
Try using the ToolStripPanel control instead. It doesn't work too well in the designer (which is probably why it isn't in the ToolBox by default).
Example:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.IsMdiContainer = true;
ToolStripPanel leftPanel = new ToolStripPanel() { Dock = DockStyle.Left };
ToolStripPanel topPanel = new ToolStripPanel() { Dock = DockStyle.Top };
this.Controls.Add(leftPanel);
this.Controls.Add(topPanel);
ToolStrip ts = new ToolStrip() { Dock = DockStyle.Fill };
ToolStripButton tsb = new ToolStripButton("Test", SystemIcons.Application.ToBitmap());
ts.Items.Add(tsb);
topPanel.Controls.Add(ts);
}
}

winforms panels vs java swing panels

In java swing I can insert panels into panels and so on, and not have to build a brand new window for every view of my applicaiton, or mess around removing and adding controls.
Theres a panel clas sin C# however I cant see any way of creating a 'panel form' or basically just a form in form designer thats a panel and its contents.
How do I do this then and work the way I did with java swing?
Usually i just dock different forms within eachother setting the IsMdiContainer Property to true on the parent window. Then i create subforms that i dock using the following function:
static class FormUtil
{
static public void showForm(Form sender, Control reciever)
{
sender.ControlBox = false;
sender.FormBorderStyle = FormBorderStyle.None;
sender.ShowInTaskbar = false;
sender.TopLevel = false;
sender.Visible = true;
sender.Dock = DockStyle.Fill;
reciever.Controls.Clear(); //clear panel first
reciever.Controls.Add(sender);
}
}
then whenever i need to dock a form inside a panel on the parents form i just do:
FormUtil.showForm(new SomeForm(), this.splitContainer1.Panel1);
This allows me to delegate some of the form creation to different designers. Works like a charm for me, love to hear if theres a better way of doing it.
Actually, you can use the panel control and set it's Dock property to Fill. That way, your panel will be the entire canvas of the form. Then, you can add child panels as needed either through code behind or through forms designer.
There's the concept of user controls which basicly provides you with a panel like designer surface , not to mention that you can create atomic forms (which can be reused) and register them as inheritable, that way you can provide inheritance too.

Categories

Resources