FormStartPosition.CenterParent 不起作用

发布于 2024-12-22 03:14:46 字数 1144 浏览 4 评论 0原文

在下面的代码中,只有第二种方法适合我(.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); 
  }
}

In the following code, only the second method works for me (.NET 4.0). FormStartPosition.CenterParent does not center the child form over its parent.
Why?

Source: this SO question

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

孤凫 2024-12-29 03:14:46

这是因为您没有告诉 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.ShowDialog(f1);

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

This is because you are not telling f2 who its Parent is.

If this is an MDI application, then f2 should have its MdiParent set to f1.

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

If this is not an MDI application, then you need to call the ShowDialog method using f1 as the parameter.

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

Note that CenterParent does not work correctly with Show since there is no way to set the Parent, so if ShowDialog is not appropriate, the manual approach is the only viable one.

与风相奔跑 2024-12-29 03:14:46

如果您像这样设置子表单的所有者

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

If you set the owner of the child form like so:

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

You can then center it easily like 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);
}
负佳期 2024-12-29 03:14:46

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

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

I'm using this code inside my main form, hope it helps:

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));
}
分开我的手 2024-12-29 03:14:46

我发现在一些更复杂的情况下,当表单自动调整大小和动态修改时,手动设置位置是唯一可靠的选择。

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

this.CenterToParent();

I found setting the location manually is the only reliable option in some more complex cases when form is auto-sized and dynamically modified.

However rather than computing the coordinates manually, I'd suggest using existing method:

this.CenterToParent();
虚拟世界 2024-12-29 03:14:46

我遇到了同样的问题,我最终选择了这个:

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

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

I had the same problem, I eventually went with this:

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

Used as:

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

The main advantage is that it does what your colleagues expect it to do, without requiring any hack in the calling form.

不离久伴 2024-12-29 03:14:46

我找到了一个解决方案,它将无模式窗口位置居中到父窗口的位置,并且子窗口仍然可以被父窗口覆盖。
您只需调用

f2.Show(f1);

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

接下来你设置

f2.Owner = null;

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

I found a solution that will center modeless window position to parent's position, and the child window can be still covered by parent window.
You just have to call

f2.Show(f1);

which will set f2 owner to f1, f2 will show over the f1 at it's center position.

Next you set

f2.Owner = null;

and there you go, f2 is a separate window, with correct startup position.

南风几经秋 2024-12-29 03:14:46

我意识到这是一个老问题,但我最近遇到了同样的问题,并且由于我不会进入的原因,我不想使用 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;           
    } 

如果您有一个可调整大小的父窗体,并且您希望子窗体在主窗体大小调整时也居中,那么理论上您应该能够将此代码放在一个方法中,然后在 LocationChanged 和 SizeChanged 上调用该方法事件。

I realize this is an old question, but I was recently having the same problem and for reasons I won't get in to, I did not want to use the form.ShowDialog() method and my application was not an MDI application, therefore the CenterParent method was not having any effect. This is how I solved the problem, by computing the coordinates for the form that I wanted centered and triggering the new location in the main form's LocationChanged event. Hopefully this will help someone else having this problem.

In the example below, the parent form is called MainForm and the form I want centered in MainForm is called 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;           
    } 

If you have a resizable parent form and you wanted your sub form to also be centered whenever the main form is resized, you should, in theory, be able to place this code in a method and then call the method on both the LocationChanged and SizeChanged events.

谁的新欢旧爱 2024-12-29 03:14:46

JYelton 的答案对我有用,但表单仅在第一次调用 Show() 时居中。
如果您想 Hide() 表单,然后在每次调用 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);
}

JYelton's answer worked for me, but the form is only centered the first time Show() is called.
If you want to Hide() the form, and then have it re-centered on the parent every time Show() is called you need use the following in your form:

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);
}
十二 2024-12-29 03:14:46

也许这可以帮助某人。

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;

Maybe this can help somebody.

Form frmMessage = new Form();

From experience, although they look similar, they behave different:

This variant doesn't work:

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

And this variant works

if (frmMessage.Parent != null)
    frmMessage.StartPosition = FormStartPosition.CenterParent;
else
    frmMessage.StartPosition = FormStartPosition.CenterScreen;
踏雪无痕 2024-12-29 03:14:46

则使用

form.Show(this);

如果您第二次调用它, 会引发异常。手动设置位置似乎是唯一可靠的选择:/(CenterParent 不是最近才开始工作的吗?)

Using

form.Show(this);

throws an exception if you call it a second time. Manually setting the location seems to be the only reliable option :/ (wasn't it fairly recently that CenterParent used to work?)

溺孤伤于心 2024-12-29 03:14:46

只需将代码放入表单的构造函数中即可。

    public FrmSample()
    {
        InitializeComponent();

        // must be after the InitializeComponent()
        this.StartPosition = FormStartPosition.CenterParent;
    }

just put the code in the constructor of your form.

    public FrmSample()
    {
        InitializeComponent();

        // must be after the InitializeComponent()
        this.StartPosition = FormStartPosition.CenterParent;
    }
未央 2024-12-29 03:14:46

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

Small Change to JYelton's answer

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);
}
我也只是我 2024-12-29 03:14:46

我知道,这是一个老问题,但我也遇到了同样的问题,但原因不同。

我打开的表单有一个被重写的 OnLoad 方法:

protected override void OnLoad(EventArgs e)
{
   //... etc.
}

但没有调用基本实现 因为它必须这样做

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

在派生类中重写 OnLoad(EventArgs) 时,请务必调用基类的 OnLoad(EventArgs) 方法,以便注册的委托接收事件。

An old question, I know, but I had the same issue but for a different reason.

The Form I was opening had an overridden OnLoad method:

protected override void OnLoad(EventArgs e)
{
   //... etc.
}

but was not calling the base implementation as it must do:

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

When overriding OnLoad(EventArgs) in a derived class, be sure to call the base class's OnLoad(EventArgs) method so that registered delegates receive the event.

再见回来 2024-12-29 03:14:46

建立 deerchao 的答案,

if (form.StartPosition == FormStartPosition.CenterParent) {
    form.Location = new Point(Location.X + (Width - form.Width) / 2, Location.Y + (Height - form.Height) / 2);
}

在 form.Show() 之后执行此操作,这也适用于多显示器

Building off the answer by deerchao,

if (form.StartPosition == FormStartPosition.CenterParent) {
    form.Location = new Point(Location.X + (Width - form.Width) / 2, Location.Y + (Height - form.Height) / 2);
}

Do this after form.Show(), this will work on multi-monitors also

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文