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