Newbiee
Newbiee

Reputation:

Show a child form in the centre of Parent form in C#

I create a new form and call from the parent form as follows:

loginForm = new SubLogin();   
loginForm.Show();

I need to display the child form at the centre of the parent. So,in the child form load I do the foll:`

Point p = new Point(this.ParentForm.Width / 2 - this.Width / 2, this.ParentForm.Height / 2 - this.Height / 2);
this.Location = p;

But this is throwing error as parent form is null. I tried setting the Parent property as well, but didn't help. Any inputs on this?

Upvotes: 93

Views: 165192

Answers (20)

Vermis
Vermis

Reputation: 2278

Here is a function that you can use to center a form on another form while ensuring that the target form is fully visible on the screen if the parent form is near the edge. This is for use in cases where you do not want to have a blocking dialog with ShowDialog() or you do not want to put this.CenterToParent() in your target form's load event.

/// <summary>
/// Change the position of the target form to be centered on the parent form while ensuring
/// that the target form is fully visible on the screen that the parent form is on in a
/// multiple monitor scenario or where the parent form is near the screen edge.
/// </summary>
/// <param name="parent">Parent form</param>
/// <param name="target">Target/child form</param>
/// <remarks>Modeled after Form.CenterToParent()</remarks>
/// <example>
/// var frm = new Form1();
//      CenterOnParentForm(this, frm);
//      frm.Show(this);
/// </example>
public void CenterOnParentForm(Form parent, Form target) {
    if (parent == null || target == null) { return; };

    target.StartPosition = FormStartPosition.Manual;

    var targetPoint = new Point();
    var parentScreen = Screen.FromControl(parent);

    if (parentScreen == null) {
        // Something terrible, let's just center on primary screen
        var primaryScreenRect = Screen.PrimaryScreen.WorkingArea;
        targetPoint.X = Math.Max(primaryScreenRect.X, primaryScreenRect.X + (primaryScreenRect.Width - target.Width) / 2);
        targetPoint.Y = Math.Max(primaryScreenRect.Y, primaryScreenRect.Y + (primaryScreenRect.Height - target.Height) / 2);
    }
    else {
        var parentScreenArea = parentScreen.WorkingArea; // Screen minus taskbar
        
        targetPoint.X = parent.Location.X + ((parent.Size.Width - target.Size.Width) / 2);
        targetPoint.Y = parent.Location.Y + ((parent.Size.Height - target.Size.Height) / 2);

        // Adjust target location to not overlap off of or onto another screen
        if (targetPoint.X < parentScreenArea.X) {
            targetPoint.X = parentScreenArea.X;
        }
        else if (targetPoint.X + target.Size.Width > parentScreenArea.X + parentScreenArea.Width) {
            targetPoint.X = parentScreenArea.X + parentScreenArea.Width - target.Size.Width;
        }

        if (targetPoint.Y < parentScreenArea.Y) {
            targetPoint.Y = parentScreenArea.Y;
        }
        else if (targetPoint.Y + target.Size.Height > parentScreenArea.Y + parentScreenArea.Height) {
            targetPoint.Y = parentScreenArea.Y + parentScreenArea.Height - target.Size.Height;
        }
    }

    target.Location = targetPoint;
}

Upvotes: 0

Quintin Robinson
Quintin Robinson

Reputation: 82325

Try:

loginForm.StartPosition = FormStartPosition.CenterParent;
loginForm.ShowDialog(this);

Of course the child form will now be a blocking form (dialog) of the parent window, if that isn't desired then just replace ShowDialog with Show..

loginForm.Show(this);

You will still need to specify the StartPosition though.

Upvotes: 152

Hasan Uddin
Hasan Uddin

Reputation: 492

As a sub form i think it's not gonna Start in the middle of the parent form until you Show it as a Dialog. .......... Form2.ShowDialog();

i was about to make About Form. and this is perfect that's i am searching for. and untill you close the About_form you cant Touch/click anythings of parents Form once you Click for About_Form (in my case) .Coz its Showing as Dialog

Upvotes: 0

Digital3D
Digital3D

Reputation: 161

When you want to use a non-blocking window (show() instead of showDialog()), this not work:

//not work with .Show(this) but only with .ShowDialog(this)
loginForm.StartPosition = FormStartPosition.CenterParent;
loginForm.Show(this);

In this case, you can use this code to center child form before display the form:

//this = the parent
frmDownloadPercent frm = new frmDownloadPercent();
frm.Show(this); //this = the parent form
//here the tips
frm.Top = this.Top + ((this.Height / 2) - (frm.Height / 2));
frm.Left = this.Left + ((this.Width / 2) - (frm.Width / 2));

Upvotes: 4

ChRoNoN
ChRoNoN

Reputation: 900

    protected override void OnLoad(EventArgs e) {
        base.OnLoad(e);

        CenterToParent();
    }

Upvotes: -2

Garuda prasad K
Garuda prasad K

Reputation: 352

If any windows form(child form) is been opened from a new thread of Main window(parent form) then its not possible to hold the sub window to the center of main window hence we need to fix the position of the sub window manually by means of X and Y co-ordinates.

In the properties of Subwindow change the "StartPosition" to be "Manual"

code in main window

private void SomeFunction()
{
    Thread m_Thread = new Thread(LoadingUIForm);
    m_Thread.Start();
    OtherParallelFunction();
    m_Thread.Abort();
}

private void LoadingUIForm()
{
    m_LoadingWindow = new LoadingForm(this);
    m_LoadingWindow.ShowDialog();
}

code in subwindow for defining its own position by means of parent current position as well as size

public LoadingForm(Control m_Parent)
{
   InitializeComponent();
   this.Location = new Point( m_Parent.Location.X+(m_Parent.Size.Width/2)-(this.Size.Width/2),
                              m_Parent.Location.Y+(m_Parent.Size.Height/2)-(this.Size.Height/2)
                            );
}

Here the co-ordinates of center of parent is calculated as well as the subwindow is kept exactly at the center of the parent by calculating its own center by (this.height/2) and (this.width/2) this function can be further taken for parent relocated events also.

Upvotes: 0

Fernando Rossato
Fernando Rossato

Reputation: 69

It works in all cases, swap Form1 for your main form.

Popup popup = new Popup();
popup.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
popup.Location = new System.Drawing.Point((Form1.ActiveForm.Location.X + Form1.ActiveForm.Width / 2) - (popup.Width / 2),(Form1.ActiveForm.Location.Y + Form1.ActiveForm.Height / 2) - (popup.Height / 2));
popup.Show(Form1.ActiveForm);

Upvotes: 3

Highflier
Highflier

Reputation: 451

The setting of parent does not work for me unless I use form.ShowDialog();.

When using form.Show(); or form.Show(this); nothing worked until I used, this.CenterToParent();. I just put that in the Load method of the form. All is good.

Start position to the center of parent was set and does work when using the blocking showdialog.

Upvotes: 44

iCode
iCode

Reputation: 1346

You can set the StartPosition in the constructor of the child form so that all new instances of the form get centered to it's parent:

public MyForm()
{
    InitializeComponent();

    this.StartPosition = FormStartPosition.CenterParent;
}

Of course, you could also set the StartPosition property in the Designer properties for your child form. When you want to display the child form as a modal dialog, just set the window owner in the parameter for the ShowDialog method:

private void buttonShowMyForm_Click(object sender, EventArgs e)
{
    MyForm form = new MyForm();
    form.ShowDialog(this);
}

Upvotes: 0

tqk2811
tqk2811

Reputation: 567

childform = new Child();
childform.Show(this);

In event childform load

this.CenterToParent();

Upvotes: 7

Lex van Buiten
Lex van Buiten

Reputation: 138

If you want to calculate your own location, then first set StartPosition to FormStartPosition.Manual:

Form Child = new Form();
Child.StartPosition = FormStartPosition.Manual;
Child.Location = new Point(Location.X + (Width - Child.Width) / 2, Location.Y + (Height - Child.Height) / 2);
Child.Show(this);

Where this is the main/parent form, just like Location.X.

Default value for StartPosition is FormStartPosition.CenterParent and therefore it changes the child's location after showing.

Upvotes: 2

Yousuf Azad
Yousuf Azad

Reputation: 415

If you have to center your childForm, from childForm then the code will be something like this. This code is in the childForm.cs

this.Show(parent as Form);    // I received the parent object as Object type
this.CenterToParent();

Upvotes: -1

Hessy SharpSabre
Hessy SharpSabre

Reputation: 152

Make a Windows Form , then put option for it : CenterParent then use this Code :

yourChildFormName x = new yourChildFormName();
x.ShowDialog();

Upvotes: 0

quixoteloco
quixoteloco

Reputation: 1

Why not use this?

LoginForm.WindowStartupLocation = Windows.WindowStartupLocation.CenterOwner 

(vb.net)

Upvotes: -4

timothy
timothy

Reputation: 588

When launching a form inside an MDIForm form you will need to use .CenterScreen instead of .CenterParent.

FrmLogin f = new FrmLogin();
f.MdiParent = this;
f.StartPosition = FormStartPosition.CenterScreen;
f.Show();

Upvotes: 9

There seems to be a confusion between "Parent" and "Owner". If you open a form as MDI-form, i.e. imbedded inside another form, then this surrounding form is the Parent. The form property StartPosition with the value FormStartPosition.CenterParent refers to this one. The parameter you may pass to the Show method is the Owner, not the Parent! This is why frm.StartPosition = FormStartPosition.CenterParent does not work as you may expect.

The following code placed in a form will center it with respect to its owner with some offset, if its StartPosition is set to Manual. The small offset opens the forms in a tiled manner. This is an advantage if the owner and the owned form have the same size or if you open several owned forms.

protected override void OnShown(EventArgs e)
{
    base.OnShown(e);
    if (Owner != null && StartPosition == FormStartPosition.Manual) {
        int offset = Owner.OwnedForms.Length * 38;  // approx. 10mm
        Point p = new Point(Owner.Left + Owner.Width / 2 - Width / 2 + offset, Owner.Top + Owner.Height / 2 - Height / 2 + offset);
        this.Location = p;
    }
}

Upvotes: 22

Stefan Steiger
Stefan Steiger

Reputation: 82146

You need this:

Replace Me with this.parent, but you need to set parent before you show that form.

  Private Sub ÜberToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ÜberToolStripMenuItem.Click

        'About.StartPosition = FormStartPosition.Manual ' !!!!!
        About.Location = New Point(Me.Location.X + Me.Width / 2 - About.Width / 2, Me.Location.Y + Me.Height / 2 - About.Height / 2)
        About.Show()
    End Sub

Upvotes: 4

jean
jean

Reputation: 1037

The parent probably isn't yet set when you are trying to access it.

Try this:

loginForm = new SubLogin();
loginForm.Show(this);
loginForm.CenterToParent()

Upvotes: -1

Matthew Scharley
Matthew Scharley

Reputation: 132234

Assuming your code is running inside your parent form, then something like this is probably what you're looking for:

loginForm = new SubLogin();
loginForm.StartPosition = FormStartPosition.CenterParent
loginForm.Show(this);

For the record, there's also a Form.CenterToParent() function, if you need to center it after creation for whatever reason too.

Upvotes: 15

BFree
BFree

Reputation: 103742

On the SubLogin Form I would expose a SetLocation method so that you can set it from your parent form:

public class SubLogin : Form
{
   public void SetLocation(Point p)
   {
      this.Location = p;
   }
} 

Then, from your main form:

loginForm = new SubLogin();   
Point p = //do math to get point
loginForm.SetLocation(p);
loginForm.Show();

Upvotes: 2

Related Questions