【问题标题】:Show a child form in the centre of Parent form in C#在 C# 的父窗体的中心显示一个子窗体
【发布时间】:2010-10-31 00:03:03
【问题描述】:

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

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;

但这会引发错误,因为父表单为空。我也尝试设置 Parent 属性,但没有帮助。对此有何意见?

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    试试:

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

    当然,子窗口现在将成为父窗口的阻止表单(对话框),如果不需要,只需将 ShowDialog 替换为 Show..

    loginForm.Show(this);
    

    您仍然需要指定 StartPosition。

    【讨论】:

    • 您也可以在设计器中设置 LoginForm 的该属性。
    • loginForm.StartPosition = FormStartPosition.CenterParent 加上 loginForm.Show(this);不使表单居中。
    • @Pedro77 我有类似的情况,只是我从不同的线程完成了显示对话框,所以它不会让我将“this”传递给 showDialog。这里有什么建议吗??
    • @Anil 我认为你不应该从不同的线程创建 UI 元素。您应该对该任务使用 invoke begininvoke。看看这些命令。
    【解决方案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();
    

    【讨论】:

      【解决方案3】:

      假设您的代码在您的父表单中运行,那么您可能正在寻找类似这样的内容:

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

      作为记录,还有一个Form.CenterToParent() 函数,如果您在创建后出于任何原因需要将其居中。

      【讨论】:

        【解决方案4】:

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

        试试这个:

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

        【讨论】:

        • CenterToParent 不是公共方法。您需要将此方法委托为您的控件的公共方法。
        【解决方案5】:

        你需要这个:

        将 Me 替换为 this.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
        

        【讨论】:

          【解决方案6】:

          “父母”和“所有者”之间似乎存在混淆。如果您以 MDI 形式打开一个表单,即嵌入到另一个表单中,那么这个周围的表单就是父表单。值为 FormStartPosition.CenterParent 的表单属性 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;
              }
          }
          

          【讨论】:

          • 我很确定 CenterParent 也相对于 Owner 运行,至少在我使用的 .net 版本中是这样。
          • 这是唯一适合我的解决方案。但是,我不知道为什么,但是当我调用 Show 方法时,即使使用 override 关键字标记 OnShown 也不会被调用。我的解决方法是创建一个新方法 Display 调用 Show 并执行您提供的定位技巧。
          【解决方案7】:

          MDIForm 表单中启动表单时,您需要使用.CenterScreen 而不是.CenterParent

          FrmLogin f = new FrmLogin();
          f.MdiParent = this;
          f.StartPosition = FormStartPosition.CenterScreen;
          f.Show();
          

          【讨论】:

            【解决方案8】:

            为什么不使用这个?

            LoginForm.WindowStartupLocation = Windows.WindowStartupLocation.CenterOwner 
            

            (vb.net)

            【讨论】:

              【解决方案9】:

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

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

              【讨论】:

                【解决方案10】:

                如果要计算自己的位置,那么先将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,因此它会在显示后更改孩子的位置。

                【讨论】:

                  【解决方案11】:

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

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

                  【讨论】:

                    【解决方案12】:

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

                    当使用form.Show();form.Show(this); 时,在我使用this.CenterToParent(); 之前没有任何效果。 我只是把它放在表单的 Load 方法中。一切都很好。

                    父中心的起始位置已设置,并且在使用阻塞显示对话框时有效。

                    【讨论】:

                    • 如果您不想使用 ShowDialog(),这就是答案。
                    【解决方案13】:
                    childform = new Child();
                    childform.Show(this);
                    

                    在事件子窗体加载

                    this.CenterToParent();
                    

                    【讨论】:

                      【解决方案14】:

                      您可以在子窗体的构造函数中设置 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);
                      }
                      

                      【讨论】:

                        【解决方案15】:

                        它适用于所有情况,将 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);
                        

                        【讨论】:

                          【解决方案16】:

                          如果从主窗口(父窗体)的新线程打开任何窗体(子窗体),则无法将子窗体保持在主窗体的中心,因此我们需要固定子窗体的位置通过 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) this 计算自己的中心,子窗口精确地保持在父窗口的中心也可以对父重定位事件进一步采用函数。

                          【讨论】:

                            【解决方案17】:
                                protected override void OnLoad(EventArgs e) {
                                    base.OnLoad(e);
                            
                                    CenterToParent();
                                }
                            

                            【讨论】:

                              【解决方案18】:

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

                              【讨论】:

                                【解决方案19】:

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

                                我正要制作关于表格。 这是我正在寻找的完美。 并且在您关闭 About_form 之前,一旦您单击 About_Form(在我的情况下),您就无法触摸/单击父母表格的任何内容 .因为它显示为对话框

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2020-05-31
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2014-12-16
                                  • 2016-02-29
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多