在C#中将子窗体显示在父窗体中央

91

我创建了一个新表单,并从父表单中调用,如下所示:

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

我需要将子窗体显示在父窗体的中心。所以,在子窗体加载时,我执行以下操作:

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

但是这会抛出错误,因为父表单为null。我尝试设置Parent属性,但没有帮助。对此有任何建议吗?

20个回答

149

尝试:

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

当然,子窗体现在将成为父窗口的阻塞式窗体(对话框)。如果不想要这种效果,只需将 ShowDialog 替换为 Show

loginForm.Show(this);

不过,您仍需要指定StartPosition


18
您还可以在设计器中设置LoginForm的该属性。 - Tim Hoolihan
67
loginForm.StartPosition = FormStartPosition.CenterParent 加上 loginForm.Show(this) 不能使窗体居中显示。 - Pedro77
@Pedro77 我有类似的情况,只是我从不同的线程中执行了show dialog,所以它不允许我将“this”传递给showDialog。这里有什么建议吗? - Anil
1
@Anil 我认为你不应该从不同的线程创建UI元素。你应该使用invoke begininvoke来完成这个任务。看一下这些命令。 - Pedro77

42

除非我使用form.ShowDialog();,否则父级设置对我无效。

当使用form.Show();form.Show(this);时,除非我使用this.CenterToParent();,否则什么都不起作用。 我只是将其放在表单的Load方法中。一切都好了。

启动位置设置为父级中心,并且在使用阻塞showdialog时有效。


1
如果您不想使用ShowDialog(),那么这就是答案。 - dpberry178

21

"Parent"和"Owner"之间似乎存在一些混淆。如果您将一个窗体作为MDI窗体打开,即嵌入到另一个窗体内部,则该周围的窗体是“Parent”。具有值FormStartPosition.CenterParent的form属性StartPosition指的是这个窗体。您可以传递给Show方法的参数是Owner,而不是Parent!这就是为什么frm.StartPosition = FormStartPosition.CenterParent不能按预期工作的原因。

如果设置了其StartPosition为Manual,则下面的代码将放置在表单中使其相对于其所有者居中并带有一些偏移量。如果所有者和所拥有的形式具有相同的大小或者您打开多个所拥有的形式,则小偏移会以平铺方式打开形式。这是一个优点。

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;
    }
}

1
我非常确定CenterParent也是相对于Owner操作的,至少在我使用的.net版本中是这样。 - binki
这是我唯一有效的解决方案。但是,我不知道为什么,当我调用Show方法时,即使它标记为override关键字,OnShown也不会被调用。我的解决方法是创建一个新的Display方法,调用Show并执行您提供的位置技巧。 - Samuel

15

假设你的代码运行在父表单内,那么以下代码可能是你要寻找的:

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

值得一提的是,如果你需要在创建后将其居中显示,还有一个 Form.CenterToParent() 函数可用。


9
当在 MDIForm 表单中启动表单时,您需要使用 .CenterScreen 而不是 .CenterParent
FrmLogin f = new FrmLogin();
f.MdiParent = this;
f.StartPosition = FormStartPosition.CenterScreen;
f.Show();

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

在子表单加载事件中
this.CenterToParent();

4
你需要这样做:
在显示表格之前,用this.parent替换Replace Me,但你需要设置父级。
  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

4

当您想要使用非阻塞窗口(show()而不是showDialog())时,这个方法不起作用:

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

在这种情况下,您可以使用此代码在显示表单之前将子表单居中:
//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));

3
在所有情况下都起作用,将Form1替换为你的主窗体。
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);

2
在SubLogin表单上,我会暴露一个SetLocation方法,以便您可以从父表单中设置它:
public class SubLogin : Form
{
   public void SetLocation(Point p)
   {
      this.Location = p;
   }
} 

然后,从您的主表单开始:
loginForm = new SubLogin();   
Point p = //do math to get point
loginForm.SetLocation(p);
loginForm.Show();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接