FormStartPosition.CenterParent不起作用

在下面的代码中,只有第二种方法适用于我(.NET 4.0)。 FormStartPosition.CenterParent不会将子表单置于其父表单的中心。 为什么?

资料来源: 这个问题

 using System; using System.Drawing; using System.Windows.Forms; class Program { private static Form f1; public static void Main() { f1 = new Form() { Width = 640, Height = 480 }; f1.MouseClick += f1_MouseClick; Application.Run(f1); } static void f1_MouseClick(object sender, MouseEventArgs e) { Form f2 = new Form() { Width = 400, Height = 300 }; switch (e.Button) { case MouseButtons.Left: { // 1st method f2.StartPosition = FormStartPosition.CenterParent; break; } case MouseButtons.Right: { // 2nd method f2.StartPosition = FormStartPosition.Manual; f2.Location = new Point( f1.Location.X + (f1.Width - f2.Width) / 2, f1.Location.Y + (f1.Height - f2.Height) / 2 ); break; } } f2.Show(f1); } } 

这是因为你没有告诉f2它的Parent是谁。

如果这是MDI应用程序,则f2应将其MdiParent设置为f1

 Form f2 = new Form() { Width = 400, Height = 300 }; f2.StartPosition = FormStartPosition.CenterParent; f2.MdiParent = f1; f2.Show(); 

如果这不是MDI应用程序,则需要使用f1作为参数调用ShowDialog方法。

 Form f2 = new Form() { Width = 400, Height = 300 }; f2.StartPosition = FormStartPosition.CenterParent; f2.Show(f1); 

请注意, CenterParent无法设置Parent ,因此CenterParent无法与Show一起正常工作,因此如果ShowDialog不合适,则手动方法是唯一可行的方法。

如果您设置子表单的所有者 ,如下所示:

 Form2 f = new Form2(); f.Show(this); 

然后你可以像这样轻松地集中它:

 Form2_Load(object sender, EventArgs e) { if (Owner != null) Location = new Point(Owner.Location.X + Owner.Width / 2 - Width / 2, Owner.Location.Y + Owner.Height / 2 - Height / 2); } 

我在我的主窗体中使用此代码,希望它有所帮助:

 var form = new MyForm(); form.Show(); if (form.StartPosition == FormStartPosition.CenterParent) { var x = Location.X + (Width - form.Width) / 2; var y = Location.Y + (Height - form.Height) / 2; form.Location = new Point(Math.Max(x, 0), Math.Max(y, 0)); } 

我发现当表单自动resize并动态修改时,手动设置位置是一些更复杂的情况下唯一可靠的选项。

但是,我建议使用现有方法,而不是手动计算坐标:

 this.CenterToParent(); 

我找到了一个解决方案,它将无模式窗口位置置于父级的位置,子窗口仍然可以被父窗口覆盖。 你只需要打电话

 f2.Show(f1); 

将f2所有者设置为f1,f2将显示在f1的中心位置。

接下来你设置

 f2.Owner = null; 

你走了,f2是一个单独的窗口,具有正确的启动位置。

我意识到这是一个老问题,但我最近遇到了同样的问题,并且由于我不会进入的原因,我不想使用form.ShowDialog()方法而我的应用程序不是MDI应用程序,因此CenterParent方法没有任何效果。 这就是我通过计算我想要居中的表单的坐标并在主窗体的LocationChanged事件中触发新位置来解决问题的方法。 希望这可以帮助其他人解决这个问题。

在下面的示例中,父窗体称为MainForm,我希望在MainForm中居中的窗体称为pleaseWaitForm。

 private void MainForm_LocationChanged(object sender, EventArgs e) { Point mainFormCoords = this.Location; int mainFormWidth = this.Size.Width; int mainFormHeight = this.Size.Height; Point mainFormCenter = new Point(); mainFormCenter.X = mainFormCoords.X + (mainFormWidth / 2); mainFormCenter.Y = mainFormCoords.Y + (mainFormHeight / 2); Point waitFormLocation = new Point(); waitFormLocation.X = mainFormCenter.X - (pleaseWaitForm.Width / 2); waitFormLocation.Y = mainFormCenter.Y - (pleaseWaitForm.Height / 2); pleaseWaitForm.StartPosition = FormStartPosition.Manual; pleaseWaitForm.Location = waitFormLocation; } 

如果你有一个可resize的父表单,并且你希望你的子表单也可以在调整主表单大小时居中,理论上你应该能够将这个代码放在一个方法中,然后在LocationChanged和SizeChanged上调用该方法事件。

JYelton的答案对我有用,但表单只在第一次调用Show()时居中。 如果你想隐藏()表单,然后每次调用Show()时让它重新居中于父表单,你需要在表单中使用以下内容:

 public new void Show(IWin32Window owner) { base.Show(owner); if (Owner != null) Location = new Point(Owner.Location.X + Owner.Width / 2 - Width / 2, Owner.Location.Y + Owner.Height / 2 - Height / 2); } 

我遇到了同样的问题,我最终还是这样做了:

 protected override void OnActivated(EventArgs e) { if(this.Modal == false && this.StartPosition == FormStartPosition.CenterParent) { if(!(this.Owner is Form)) { // Center to the last form opened before this one int numforms = Application.OpenForms.Count; this.Owner = Application.OpenForms[numforms - 2]; } this.CenterToParent(); Application.DoEvents(); } base.OnActivated(e); } 

用作:

 MyForm form = new MyForm(); form.Show(this); // with or without 

主要优点是它可以完成您的同事所期望的操作,而不需要在调用表单中进行任何操作。

运用

 form.Show(this); 

如果你第二次调用它会引发exception。 手动设置位置似乎是唯一可靠的选项:/(最近CenterParent曾经工作过吗?)

也许这可以帮助某人。

 Form frmMessage = new Form(); 

从经验来看,虽然看起来很相似,但它们表现不同:

此变体不起作用:

 if (frmMessage.Parent != null) frmMessage.CenterToParent(); else frmMessage.CenterToScreen(); 

这种变体有效

 if (frmMessage.Parent != null) frmMessage.StartPosition = FormStartPosition.CenterParent; else frmMessage.StartPosition = FormStartPosition.CenterScreen; 

对JYelton的回答微不足道

 Form2_Load(object sender, EventArgs e) { if (Owner != null && Parent == null && StartPosition == FormStartPosition.CenterParent) Location = new Point(Owner.Location.X + Owner.Width / 2 - Width / 2, Owner.Location.Y + Owner.Height / 2 - Height / 2); }