在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个回答

2

如果您想计算自己的位置,则首先将StartPosition设置为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);

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

StartPosition的默认值为FormStartPosition.CenterParent,因此在显示后会更改子窗体的位置。


0

您可以在子窗体的构造函数中设置StartPosition属性,以便所有新实例的窗体都居中于其父窗体:

public MyForm()
{
    InitializeComponent();

    this.StartPosition = FormStartPosition.CenterParent;
}

当然,您也可以在设计器属性中设置子窗体的StartPosition属性。当您想要将子窗体显示为模态对话框时,只需在ShowDialog方法的参数中设置窗口所有者即可:
private void buttonShowMyForm_Click(object sender, EventArgs e)
{
    MyForm form = new MyForm();
    form.ShowDialog(this);
}

0
如果从主窗口(父窗口)的新线程中打开任何Windows表单(子窗口),则无法将子窗口保持在主窗口的中心,因此我们需要通过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
创建一个 Windows 窗体,然后为其添加选项:CenterParent,接着使用以下代码:
yourChildFormName x = new yourChildFormName();
x.ShowDialog();

0

作为子窗体,我认为它不会在父窗体的中间开始,除非你将其显示为对话框。 .......... Form2.ShowDialog();

我正要制作关于窗体。 这很完美,这就是我正在寻找的。 在关闭 About_form 之前,您不能触摸/单击任何父窗体的内容,一旦您点击 About_Form(在我的情况下)。 因为它显示为对话框。


0
这里有一个函数,你可以用它来将一个表单居中显示在另一个表单上,同时确保如果父表单靠近屏幕边缘,目标表单完全可见。这适用于那些你不想使用阻塞对话框 ShowDialog() 或者不想在目标表单的加载事件中使用 this.CenterToParent() 的情况。
/// <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;
}

-1

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

请尝试以下操作:

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

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

-1
如果你需要在子窗体中心对齐,那么代码应该是这样的。这段代码位于childForm.cs文件中。
this.Show(parent as Form);    // I received the parent object as Object type
this.CenterToParent();

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

        CenterToParent();
    }

-4
为什么不使用这个?
LoginForm.WindowStartupLocation = Windows.WindowStartupLocation.CenterOwner 

(vb.net)


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