在C#的“父”表单的中心显示子表单


76

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

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属性,但没有帮助。有什么意见吗?

Answers:


134

尝试:

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

当然,子级现在将是父窗口的阻止形式(对话框),如果不需要,则只需替换ShowDialogShow.。

loginForm.Show(this);

但是,您仍然需要指定StartPosition。


16
您还可以在设计器中设置LoginForm的该属性。
Tim Hoolihan,2009年

53
loginForm.StartPosition = FormStartPosition.CenterParent加上loginForm.Show(this); 不居中窗体。
Pedro77

@ Pedro77我有一个类似的情况,除了我从不同的线程执行了显示对话框,因此它不会让我将“ this”传递给showDialog。这里有什么建议吗?
阿尼尔

1
@Anil我认为您不应该从其他线程创建UI Itens。您应该对该任务使用invoke begininvoke。看一下这些命令。
Pedro77

20

除非我使用,否则parent的设置对我不起作用form.ShowDialog();

使用时,form.Show();form.Show(this);直到我使用为止,没有任何作用this.CenterToParent();。我只是将其放在表单的Load方法中。一切都很好。

设置到父中心的起始位置,并且在使用阻止显示对话框时可以正常工作。


18

“父母”和“所有者”之间似乎有些混淆。如果您以MDI表单的形式打开表单,即将其嵌入另一个表单中,则该周围的表单就是父表单。具有值FormStartPosition.CenterParent的表单属性StartPosition引用了这一点。您可能会传递给Show方法的参数是所有者,而不是父级!这就是为什么frm.StartPosition = FormStartPosition.CenterParent无法正常工作的原因。

如果将其放置在表单中的以下代码将其StartPosition设置为“手动”,则它将相对于其所有者以一定的偏移量居中。小偏移量以平铺方式打开表单。如果所有者和拥有的表单具有相同的大小,或者如果您打开多个拥有的表单,则这是一个优势。

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

我很确定,至少CenterParent相对于Owner我使用的.net版本,它也可以相对运行。
2015年

12

假设您的代码正在父窗体中运行,那么您可能正在寻找这样的东西:

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


4

你需要这个:

用this.parent代替Me,但是在显示该表单之前,您需要设置parent。

  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

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

2

如果要计算自己的位置,请首先设置StartPositionFormStartPosition.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);

这是主/父表单,就像Location.X。

的默认值StartPositionFormStartPosition.CenterParent,因此显示后会更改孩子的位置。


2

当您要使用非阻塞窗口(用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));

这应该是选择的答案!!!+1
Si8 20年

0

制作一个Windows窗体,然后为其放置选项:CenterParent,然后使用此代码:

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

0

您可以在子窗体的构造函数中设置StartPosition,以使窗体的所有新实例都集中在其父窗体的中央:

public MyForm()
{
    InitializeComponent();

    this.StartPosition = FormStartPosition.CenterParent;
}

当然,您也可以在子窗体的Designer属性中设置StartPosition属性。当您想将子窗体显示为模式对话框时,只需在ShowDialog方法的参数中设置窗口所有者:

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

0

如果从主窗口(父窗体)的新线程中打开了任何窗口窗体(子窗体),则不可能将子窗口保持在主窗口的中心,因此我们需要通过以下方式手动确定子窗口的位置: X和Y坐标的平均值。

在子窗口的属性中,将“ StartPosition”更改为“ Manual”

主窗口中的代码

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

子窗口中的代码,用于通过父代当前位置以及大小来定义其自身位置

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

通过计算此函数的自身中心(this.height / 2)和(this.width / 2),可以计算父中心的坐标,并将子窗口精确地保持在父中心。进一步考虑了父级迁移事件。


0

作为子表单,我认为在您将其显示为对话框之前,它不会在父表单的中间开始。 .......... Form2.ShowDialog();

我正要制作About Form。这就是我正在寻找的完美选择。然后直到您关闭About_form后,您才能单击/单击About_Form(在我的情况下),无法触摸/单击任何形式的父窗体。


-1

当您尝试访问父级时,父级可能尚未设置。

尝试这个:

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

3
CenterToParent不是公共方法。您需要从控件中将此方法委托为公共方法。
Jarek

-1

如果您必须将childForm居中,则childForm中的代码将是这样的。这段代码在childForm.cs中

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

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

        CenterToParent();
    }

-4

为什么不使用这个?

LoginForm.WindowStartupLocation = Windows.WindowStartupLocation.CenterOwner 

(vb.net)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.