Form.Parent и StartPosition.CenterParent
Мне нужно показать форму точно перед другой формой, это привело меня к следующему вопросу.
Как получилось, что форма может иметь начальную позицию как CenterParent
, когда поле this.Parent
равно null?
Он должен знать родителя, чтобы правильно позиционировать его, но это поле Parent
не задано. Это странно. Я что-то пропустил?
Form2 f = new Form2();
f.ShowDialog();
Это все, что я делаю на дочерней форме. Родитель установлен в положение по умолчанию для окон. Независимо от того, где я перемещаю родительскую форму, ребенок отображается в центре родителя.
Ответы
Ответ 1
Информация о владельце передается в созданный диалог через вызов API (вы можете видеть, что в Reflector в методе ShowDialog (IWin32Window owner)):
UnsafeNativeMethods.SetWindowLong(new HandleRef(this, base.Handle), -8, new HandleRef(owner, handle));
Если в вызове ShowDialog нет владельца, переменная owner
вычисляется с помощью вызова API GetActiveWindow:
IntPtr activeWindow = UnsafeNativeMethods.GetActiveWindow();
IntPtr handle = (owner == null) ? activeWindow : Control.GetSafeHandle(owner);
Чтобы получить доступ к форме диалога Owner f, вы можете использовать вызов GetWindowLong API:
IntPtr ownerHandle = NativeMethods.GetWindowLong(nonModalForm.Handle, -8);
Ответ 2
Разница между родителем и владельцем окна немного запутана в Winforms. В этом контексте CenterParent действительно означает CenterOwner. Это не возможность Windows, она реализована в Winforms, выполняемая базовым методом Form.OnLoad(). Диалог всегда должен иметь владельца, он отключается, если вы не укажете его в вызове ShowDialog(). Что лучше всего использует GetActiveWindow().
Чтобы убедиться в этом, перегрузите OnLoad в форме диалога, например:
public partial class Form2 : Form {
public Form2() {
InitializeComponent();
this.StartPosition = FormStartPosition.CenterParent;
}
protected override void OnLoad(EventArgs e) {
//base.OnLoad(e);
}
}
Обратите внимание, что он больше не сосредотачивается на владельце.
Вы можете увидеть соответствующий код в классе Reference Source, Form.cs, OnLoad:
if (GetState(STATE_MODAL)) {
FormStartPosition startPos = (FormStartPosition)formState[FormStateStartPos];
if (startPos == FormStartPosition.CenterParent) {
CenterToParent();
}
else if (startPos == FormStartPosition.CenterScreen) {
CenterToScreen();
}
}
Ответ 3
Я полагаю, что эта информация хранится внутри .NET Framework по какой-то причине. В любом случае, если вы хотите получить доступ к родительской форме, вы можете установить ее свойство владельца дочерней формы:
Form form = new Form();
form.Owner = this;
form.Show();
Затем в дочерней форме вы можете получить доступ к родительской форме, используя свойство Owner. Когда форма принадлежит другой форме, она сворачивается и закрывается формой владельца. Собственные формы также не отображаются за их формой владельца, что является безусловным, что вам нужно, если я правильно понял вас.
Ответ 4
Этот код откроет диалог в середине родительского TAG.
ObjectDistrubution od = new ObjectDistrubution();
od.StartPosition = FormStartPosition.CenterParent;
od.ShowDialog();