次のコードでは、2番目の方法のみが機能します(.NET 4.0)。 FormStartPosition.CenterParent
は、子フォームを親の上に中央揃えしません。どうして?
出典: this SO question
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);
}
}
これは、Parent
が誰であるかf2
に知らせていないためです。
これがMDI=アプリケーションの場合、f2
のMdiParent
をf1
に設定する必要があります。
Form f2 = new Form() { Width = 400, Height = 300 };
f2.StartPosition = FormStartPosition.CenterParent;
f2.MdiParent = f1;
f2.Show();
これがMDIアプリケーションではない場合、f1
をパラメーターとして使用してShowDialog
メソッドを呼び出す必要があります。
Form f2 = new Form() { Width = 400, Height = 300 };
f2.StartPosition = FormStartPosition.CenterParent;
f2.ShowDialog(f1);
CenterParent
を設定する方法がないため、Show
はParent
では正しく機能しないことに注意してください。したがって、ShowDialog
が適切でない場合、手動によるアプローチが唯一の実行可能なもの。
子フォームのownerを次のように設定した場合:
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);
}
私のメインフォーム内でこのコードを使用しています。
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));
}
場所を手動で設定することは、フォームが自動サイズ調整されて動的に変更されるいくつかのより複雑なケースで唯一の信頼できるオプションであることがわかりました。
ただし、座標を手動で計算するのではなく、既存の方法を使用することをお勧めします。
this.CenterToParent();
モードレスウィンドウの位置を親の位置の中央に配置するソリューションを見つけましたが、子ウィンドウは引き続き親ウィンドウでカバーできます。電話するだけ
f2.Show(f1);
これにより、f2の所有者がf1に設定され、f2はその中心位置でf1の上に表示されます。
次に設定します
f2.Owner = null;
これで、f2は別のウィンドウであり、正しい起動位置にあります。
私は同じ問題を抱えていました、私は最終的にこれで行きました:
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
主な利点は、呼び出しフォームでのハッキングを必要とせずに、同僚が期待することを実行することです。
JYeltonの答えは私にとってはうまくいきましたが、フォームはShow()が初めて呼び出されたときにのみ中央揃えになります。フォームをHide()したい場合、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);
}
これは古い質問であることに気付きましたが、最近同じ問題が発生しており、理由がわからないため、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の両方でメソッドを呼び出すことができます。イベント。
多分これは誰かを助けることができます。
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;
使用する
form.Show(this);
もう一度呼び出すと、例外がスローされます。手動で場所を設定することが唯一の信頼できるオプションのようです:/(CenterParentが機能していたのはごく最近のことではないですか?)
古い質問ですが、同じ問題がありましたが、理由が異なりました。
私が開いていたフォームには、オーバーライドされたOnLoadメソッドがありました:
protected override void OnLoad(EventArgs e)
{
//... etc.
}
しかし、基本実装を呼び出していませんでした それを行う必要があるように :
protected override void OnLoad(EventArgs e)
{
//... etc.
base.OnLoad(e);
}
派生クラスでOnLoad(EventArgs)をオーバーライドする場合は、登録されているデリゲートがイベントを受け取ることができるように、基本クラスのOnLoad(EventArgs)メソッドを呼び出してください。
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);
}
コードをフォームのコンストラクターに配置するだけです。
public FrmSample()
{
InitializeComponent();
// must be after the InitializeComponent()
this.StartPosition = FormStartPosition.CenterParent;
}