I asked this question previously and thought I had it figured out but it still doesn't work.
Form.Show() moves form position slightly
So I have a parent form that opens a bunch of children with show() and then when one is needed I use bringToFront() to display it. The problem is when show() is called the child form is aligned perfectly but when I use bringToFront it moves left and down 1 px which screws with my borders. I have set all the child forms startPosition properties to Manual before show()-ing them. I have set frm.location = new Point(x,y) when bringing to front. I've also tried explicity setting frm.location when show()-ing also. It still moves it left and down 1 px when I bringToFront(). Is there something with bringToFront() that doesn't let me change the location property of the form? Here is my code:
if (myNewForm != null)
{
myNewForm.MdiParent = this;
bool isFormOpen = false;
foreach (Form frm in Application.OpenForms)
{
if (frm.GetType() == myNewForm.GetType())
{
frm.WindowState = FormWindowState.Maximized;
frm.BringToFront();
frm.Location = new Point(-4, -30);
isFormOpen = true;
break;
}
}
if (!isFormOpen)
{
myNewForm.StartPosition = FormStartPosition.Manual;
myNewForm.Show();
}
}
EDIT: Ok so apparently Microsoft has a bug that lets StartPosition only work for ShowDialog() and not Show() but refuses to fix it: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=107589
But my application needs to keep all the different forms open and just bring them to the front when needed...so ShowDialog() could not be appropriately used in this instance correct? So what options do I have? Any?
If you wish to set the form location, you have to set the form's WindowState to Normal (on any other setting, the location is set for you according to the rules of that setting, so your value is ignored), and its StartPosition to Manual.
frm.WindowState = FormWindowState.Normal;
frm.StartPosition = FormStartPosition.Manual;
frm.BringToFront();
frm.Location = new Point(-4, -30);
I suppose the forms are moved by the code that handles the Show() (and BringToFront) requests, so you really cannot set the form's location - neither before nor after calling the method - because the form location will be updated after the code in your main window has executed (and left control back to the window message pump, in Win32 terms, basically).
I would use a subclass of Form for each of your forms and then add an explicit Point property that indicates the fixed position where that particular form is expected to be. Inside this class, override the OnShown virtual method (or perhaps the OnActivated method too) and simply update this.Location with the correct location.
That should force the forms to the correct position, even if some code inside windows forms changes it at some time.
Have you tried:
this.Location
or
Form.ActiveForm.Location ?
What about using a p/Invoke to MoveWindow? The link provided includes a C# example.
Have you tried showing the form, and then adjusting the Location?
Edit: Or, have you tried adjusting the Left and Top properties?
Related
I have a very basic out the box mdiparent which has a number of mdichildren and a menu item. Each button on the menu item hides all the forms and then shows the one respective to that button.
When I do it this way:
//dontHide is the Form we want to show.
for(int i = 0; i < this.MdiChildren.Length; i++)
{
if (this.MdiChildren[i] != dontHide)
{
this.MdiChildren[i].Visible = false;
}
}
dontHide.Visible = true;
Switching forms causes the new form opened to be positioned bit lower and to the right of the old form, but clicking the menu item for the currently displayed form does nothing (as expected).
But, when I do this:
//dontHide is the Form we want to show.
for(int i = 0; i < this.MdiChildren.Length; i++)
{
this.MdiChildren[i].Visible = false;
}
dontHide.Visible = true;
Even clicking the menu item for the currently visible form causes it to shift to the lower right, same as opening a new form. Why is that?
Edit:
I've also noticed when centering the form and then displaying it (so you don't risk having someone glimpse it right before it is moved), setting visible to true completely resets any centering I've done.
This is caused by an obscure implementation detail in Winforms. The native MDI support built into Windows does not support hiding child windows. Winforms works around this restriction by destroying the child window when you set its Visible property to false. And re-creating it when you set it back to true.
This can have various side-effects, the state of the native window is lost when this happens of course. Winforms has fairly decent support for restoring the window again from its properties. But one thing it doesn't do is recreating the window in the same location. So you'll see it getting recreated in the location that new MDI child windows get, staggered from the previous window. Whether that was an oversight or intentional isn't that clear to me, 95% odds for the latter.
Otherwise simple to work around, you can assign the Location property yourself to get it back where it was:
var loc = dontHide.Location;
dontHide.Visible = true;
dontHide.Location = loc;
Or just set the MDI child form's StartPosition to Manual.
Edit
The answer to This Question, though an obvious solution, is insufficient for this case. I've bolded the reason in my original question explaining why I wanted it 'literally answered' - thanks LarsTech!
My Original Question:
I have a library with 100 WinForms Form screens in it that is 'Beyond My Control' and there are a few I can share in my app. However, my app uses a tab control and I need the content of the forms to appear within the tabs instead of as popups.
When I try to new up one of the forms and add it to the controls collection of a tab, I get this error message:
Top-level control cannot be added to a control.
Anybody know how to get around this? I know there are other ways involving better architecture, but deadlines, backlogs, and rich new customers await. [sigh/]
private void button1_Click(object sender, EventArgs e)
{
//panel1.Controls.Add(new Button());
Form f = new Form();
f.Controls.Add(new CheckBox());
//f.ShowDialog();
panel1.Controls.Add(f);
}
Try turning the TopLevel off:
f.TopLevel = false;
f.FormBorderStyle = FormBorderStyle.None;
f.Visiible = true;
Now it is essentially a UserControl. A word of caution though, since it's a form, it will show up in the Application.OpenForms collection, which is probably not your intention.
You need to set the form's TopLevel property to false, like this:
f.TopLevel = false;
You may also want to set the FormBorderStyle property to None.
f.FormBorderStyle = FormBorderStyle.None;
As mentioned in the comments above, it really would be best, when possible, to make it a UserControl.
I have a form that i want to always be on top whenever it is opened in the application but i dont want it to be on top when the main form is minimized or another application is navigated. I want it to be on top only in my application.
Following the answer in the question : How to make a window always stay on top in .Net?
this.TopMost = true;
Makes the form on top but the form is still on top when another application is navigated to or the main form is closed.
Pls how do i make the form only on top in the application while enabling user to still work on the main form?
You are looking for an owned window. It is always on top of the owner and it gets minimized along with the owner. Good examples of owned windows are the various helper windows inside Visual Studio. You can undock them but they'll always stay on top of the VS main window.
You create an owned window by displaying it with the Show(owner) overload. Or by explicitly assigning its Owner property.
Set the top level and then set the owner, example below.
public Form1()
{
InitializeComponent();
Form2 f2 = new Form2();
//top level not really needed
f2.TopLevel = true;
f2.Show(this);
}
I have a little problem with my MDI Parent Window and the MDI Childs window. The problem is that i need 3 child window but only the first it'll be maximize, so i use this code:
UserAdmin usrWindow = new UserAdmin();
usrWindow.MdiParent = this;
usrWindow.WindowState = FormWindowState.Normal;
usrWindow.Show();
For the others 2 windows i use this code:
TaskAdmin tskWindow = new TaskAdmin ();
tskWindow.MdiParent = this;
tskWindow.Show();
I only need that the first windows is maximized, but when i open the others they open maximized too.
How can i do to open one maximized and others in the default size over the first?
Thanks
That is not possible, yet can be achieved with very very tricky (using WndProc override, custom event loops) and ugly code which will not work in different operation systems in the same manner (i.e WinXP/WinXPSP1/WinXPSP3/Vista/Win7)
Your TaskAdmin forms cannot have an MDIParent in this situation. You need to either float these forms over the MDIParent or place them in panels in the MDIParent, docked to a side.
HI all,
I have this code in which the window property of making child window load at the center of mdiparent.
Form2 f = new Form2();
f.MdiParent = this;
//center screen is working.
//f.StartPosition = FormStartPosition.CenterScreen;
f.StartPosition = FormStartPosition.CenterParent;
but instead of making the child window pop at the center it loads at the left side.
Can anyone help me on this.
Please refer the screenshot below.
I have even tried doing the same in vb. Even there i get the same error. I think the property of FormStartPosition.CenterParent is dummy.
alt text http://img13.imageshack.us/img13/7003/errorprb.jpg
I experimented a bit with this, and first came to the same solution as Patrick. But I was bugged by the following statement in the documentation of the StartPosition property:
You can also position the form to
display in the center of the screen or
in the center of its parent form for
forms such as multiple-document
interface (MDI) child forms.
So, I decided that there must be a way. And there is, though I don't find it all intuitive: set the StartPosition to CenterScreen (not CenterParent):
MdiChildUI form = new MdiChildUI();
form.MdiParent = this;
form.StartPosition = FormStartPosition.CenterScreen;
form.Show();
Of course, you can also set it in the designer instead of in code.
Setting start position as center screen works perfect for me.
I tried showing the child with the MDI container form as owner, but caused an exception for me. You could manually set the location before showing the child as follows:
Form2 f = new Form2();
f.MdiParent = this;
f.StartPosition = FormStartPosition.Manual;
f.Location = new Point((this.ClientSize.Width - f.Width) / 2,
(this.ClientSize.Height - f.Height) / 2);
f.Show();
EDIT:
f.StartPosition = FormStartPosition.CenterScreen;
is the correct way to center an mdichild on its parent form.
A form has an MdiParent property and a Parent property.
Please notice that an MdiParent IS NOT the parent of MdiChild form.
It is, its MdiParent;
So CenterToParent Method is meaningless for these types of forms.
You can see the functionality of CenterToParent Method when you program for multiple monitors application, or when you host a form inside another form by setting its Toplevel property to false, and setting its Parent property to another form.
Good Luck,
Aram Afsar