Form.Parent and StartPosition.CenterParent
Asked Answered
P

4

14

I need to show a form exactly in front of another form, this lead me to the following question.

How come a form can have a start position as CenterParent while having the field this.Parent equals to null?

It must know the parent in order to position itself correctly, which it does, but the Parent field is not set. This is odd. Am I missing something?

        Form2 f = new Form2();
        f.ShowDialog();

Thats all I do on the child form. The parent is set to default windows position. No matter where I move the parent form, the child is shown in the center of the parent.

Polytechnic answered 8/6, 2012 at 8:1 Comment(10)
when you start the app im guessing the parent which isnt a parent is set to center screen based on windows natural settings, if you move this 'parent' form to say the top left corner of the screen, does the 'child' still center to that or to the center of your entire screen?Biskra
No matter where I move the parent form, the child is possitioned correctlyPolytechnic
when do you set the parent to be null? centering is done in the onload event, if you set its parent to null outside of this it could be why. it has a parent, centers, then told it doesnt have a parent afterwardsBiskra
@Biskra edited question. Let me know if you need something clarified.Polytechnic
i would hazard a guess at something isnt being done riht here, there is an SO question where someone set the parent to null then tried to centre it and it broke because there was no parent, now youre saying the exact opposite is happening, curious #945397Biskra
AHA i beleive ShowDialog is the problem here, try just Show, ShowDialog seems to be what is telling it its a child even if it isnt, atelast thats what the other SO question is saying ;DBiskra
Because the form is shown as dialog, the parent is the form that is 'owner' of the messageloop for that particular thread. (the new form itself becoming the new holder.Hollar
@Hollar how does this answers to my question? The child form at a moment chooses to position itself. How does it know the position of the parent in order to correctly position itself?Polytechnic
Precisely that: Form1 is running modally (either through showdialog or through Application.Run). That means within that thread (perhaps there is only one), Form1 is the main 'owner' of the messageloop. When Form2 is created and shown modally (dialog) on the same thread, it knows that the current modal form is Form1 and thus its parent. If there is no current modal form, the parent would became the screen it is shown in and center on the screen.Hollar
The centering does not work if the original window is not currently focused. So I recommend to always use the overload of ShowDialog() which accepts an IWin32Window, otherwise the dialog form might appear behind your main form which confuses the user when they try to interact with your application but can’t. @Me.Name, no, see the top answer, only a focused window in the current app will ever become the owner.Hartshorn
C
8

The information about the owner is passed to the created dialog via the API call (you can see that in Reflector within the ShowDialog(IWin32Window owner) method):

UnsafeNativeMethods.SetWindowLong(new HandleRef(this, base.Handle), -8, new HandleRef(owner, handle));

When there is no owner specified in ShowDialog call the owner variable is calcualated via the GetActiveWindow API call:

IntPtr activeWindow = UnsafeNativeMethods.GetActiveWindow();
IntPtr handle = (owner == null) ? activeWindow : Control.GetSafeHandle(owner);

To get access to the Owner f dialog form you can use the GetWindowLong API call:

IntPtr ownerHandle = NativeMethods.GetWindowLong(nonModalForm.Handle, -8);
Carousal answered 8/6, 2012 at 8:19 Comment(2)
Thanks DmitryG, but what is the magic that happens with ShowModal? Note that I do not pass the parent to ShowDialog() though.Polytechnic
This version of the ShowDialog method does not specify a form or control as its owner. When this version is called, the currently active window is made the owner of the dialog box. If you want to specify a specific owner, use the other version of this method. Read MSDN Remarks - msdn.microsoft.com/en-us/library/c7ykbedk.aspx. I think you can accept DmitryG's answer.Grettagreuze
E
3

The difference between a parent and an owner of a window is a bit muddled in Winforms. In this context, CenterParent really means CenterOwner. Not a Windows capability, it is implemented in Winforms, done by the base Form.OnLoad() method. A dialog should always have a owner, it goes out hunting for one when you don't specify one in the ShowDialog() call. Which uses GetActiveWindow() as the best guess.

To see this for yourself, overload OnLoad in the dialog form, like this:

public partial class Form2 : Form {
    public Form2() {
        InitializeComponent();
        this.StartPosition = FormStartPosition.CenterParent;
    }
    protected override void OnLoad(EventArgs e) {
        //base.OnLoad(e);
    }
}

And note that it no longer centers on the owner.

You can see the relevant code in the Reference Source, Form.cs class, OnLoad method:

if (GetState(STATE_MODAL)) {
    FormStartPosition startPos = (FormStartPosition)formState[FormStateStartPos];
    if (startPos == FormStartPosition.CenterParent) {
        CenterToParent();
    }
    else if (startPos == FormStartPosition.CenterScreen) {
        CenterToScreen();
    }
}
Embellish answered 8/6, 2012 at 9:42 Comment(0)
A
1

I believe this information is stored internally by .NET Framework for some reason. Anyway, if you want to have access to the parent form you can set it to Owner property of the child form:

Form form = new Form();
form.Owner = this;
form.Show();

Then in the child form you can access the parent form using the Owner property. When a form is owned by another form, it is minimized and closed with the owner form. Owned forms are also never displayed behind their owner form, which is exaclty what you need if I understood you right.

Adjustment answered 8/6, 2012 at 8:46 Comment(0)
U
0

This code will open the dialog in the middle of the parent TAG.

    ObjectDistrubution od = new ObjectDistrubution();
    od.StartPosition = FormStartPosition.CenterParent;
    od.ShowDialog();
Uball answered 7/5, 2013 at 9:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.