Подтвердить что ты не робот

FormStartPosition.CenterParent не работает

В следующем коде для меня работает только второй метод (.NET 4.0). FormStartPosition.CenterParent не центрирует дочернюю форму над ее родителем. Почему?

Источник: этот вопрос SO

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

Ответ 1

Это потому, что вы не говорите f2 кто его Parent.

Если это приложение MDI, то для f2 его MdiParent должен быть установлен в f1.

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

Если это не приложение MDI, вам нужно вызвать метод ShowDialog используя f1 в качестве параметра.

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

Обратите внимание, что CenterParent не работает правильно с Show поскольку нет способа установить Parent, поэтому, если ShowDialog не подходит, ручной подход является единственно возможным.

Ответ 2

Если вы установите владельца дочерней формы следующим образом:

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

Ответ 3

Я использую этот код внутри своей основной формы, надеюсь, что это поможет:

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

Ответ 4

Я обнаружил, что настройка местоположения вручную является единственной надежной опцией в некоторых более сложных случаях, когда форма авторазмерна и динамически модифицирована.

Однако вместо того, чтобы вручную вычислять координаты, я бы предложил использовать существующий метод:

this.CenterToParent();

Ответ 5

Я нашел решение, которое будет центрировать немодальное положение окна до родительской позиции, а дочернее окно может быть покрыто родительским окном. Вам просто нужно позвонить

f2.Show(f1);

который установит f2 владельцу f1, f2 отобразит над f1 в его центральном положении.

Затем вы устанавливаете

f2.Owner = null;

и там вы идете, f2 - отдельное окно с правильной начальной позицией.

Ответ 6

У меня была такая же проблема, я в конце концов пошел с этим:

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

Главное преимущество заключается в том, что он делает то, что ваши коллеги ожидают этого, не требуя каких-либо взломов в вызывающей форме.

Ответ 7

Я понимаю, что это старый вопрос, но у меня недавно была такая же проблема, и по причинам, в которые я не буду входить, я не хотел использовать метод 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.

Ответ 8

Ответ 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);
}

Ответ 9

Может быть, это может помочь кому-то.

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;

Ответ 10

Используя

form.Show(this);

выдает исключение, если вы его вызываете второй раз. Ручная настройка местоположения, по-видимому, является единственным надежным вариантом:/(не так ли недавно, что CenterParent работал?)

Ответ 11

Маленькое изменение на ответ 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);
}

Ответ 12

Старый вопрос, я знаю, но у меня была та же проблема, но по другой причине.

Форма, которую я открывал, содержала переопределенный метод OnLoad:

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

но не вызывал базовую реализацию , как это должно быть:

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

При переопределении OnLoad (EventArgs) в производном классе обязательно вызовите метод OnLoad (EventArgs) базового класса, чтобы зарегистрированные делегаты получили событие.

Ответ 13

просто поместите код в конструктор вашей формы.

    public FrmSample()
    {
        InitializeComponent();

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