web-dev-qa-db-ja.com

FormStartPosition.CenterParentが機能しない

次のコードでは、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); 
  }
}
34
kol

これは、Parentが誰であるかf2に知らせていないためです。

これがMDI=アプリケーションの場合、f2MdiParentf1に設定する必要があります。

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を設定する方法がないため、ShowParentでは正しく機能しないことに注意してください。したがって、ShowDialogが適切でない場合、手動によるアプローチが唯一の実行可能なもの。

35
competent_tech

子フォームの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);
}
35
JYelton

私のメインフォーム内でこのコードを使用しています。

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

場所を手動で設定することは、フォームが自動サイズ調整されて動的に変更されるいくつかのより複雑なケースで唯一の信頼できるオプションであることがわかりました。

ただし、座標を手動で計算するのではなく、既存の方法を使用することをお勧めします。

this.CenterToParent();
5
sherpa

モードレスウィンドウの位置を親の位置の中央に配置するソリューションを見つけましたが、子ウィンドウは引き続き親ウィンドウでカバーできます。電話するだけ

f2.Show(f1);

これにより、f2の所有者がf1に設定され、f2はその中心位置でf1の上に表示されます。

次に設定します

f2.Owner = null;

これで、f2は別のウィンドウであり、正しい起動位置にあります。

3
Szybki

私は同じ問題を抱えていました、私は最終的にこれで行きました:

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

主な利点は、呼び出しフォームでのハッキングを必要とせずに、同僚が期待することを実行することです。

3
primo

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

これは古い質問であることに気付きましたが、最近同じ問題が発生しており、理由がわからないため、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の両方でメソッドを呼び出すことができます。イベント。

2
smitty1

多分これは誰かを助けることができます。

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;
2
Gogu CelMare

使用する

form.Show(this);

もう一度呼び出すと、例外がスローされます。手動で場所を設定することが唯一の信頼できるオプションのようです:/(CenterParentが機能していたのはごく最近のことではないですか?)

1
DanW

古い質問ですが、同じ問題がありましたが、理由が異なりました。

私が開いていたフォームには、オーバーライドされたOnLoadメソッドがありました:

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

しかし、基本実装を呼び出していませんでした それを行う必要があるように

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

派生クラスでOnLoad(EventArgs)をオーバーライドする場合は、登録されているデリゲートがイベントを受け取ることができるように、基本クラスのOnLoad(EventArgs)メソッドを呼び出してください。

0
oatsoda

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);
}
0
D.J.

コードをフォームのコンストラクターに配置するだけです。

    public FrmSample()
    {
        InitializeComponent();

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