web-dev-qa-db-fra.com

FormStartPosition.CenterParent ne fonctionne pas

Dans le code suivant, seule la deuxième méthode fonctionne pour moi (.NET 4.0). FormStartPosition.CenterParent ne centre pas le formulaire enfant sur son parent. Pourquoi?

Source: cette 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); 
  }
}
29
kol

En effet, vous ne dites pas à f2 qui est sa Parent.

S'il s'agit d'une application MDI, alors f2 devrait avoir sa MdiParent définie sur f1.

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

S'il ne s'agit pas d'une application MDI, vous devez appeler la méthode ShowDialog en utilisant f1 comme paramètre.

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

Notez que CenterParent ne fonctionne pas correctement avec Show car il n’existe aucun moyen de définir Parent. Par conséquent, si ShowDialog n’est pas approprié, la méthode manuelle est la seule possible.

30
competent_tech

Si vous définissez le propriétaire du formulaire enfant comme suit:

Form2 f = new Form2();
f.Show(this);

Vous pouvez ensuite le centrer facilement comme ceci:

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

J'utilise ce code dans mon formulaire principal, j'espère que cela aidera:

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

J'ai constaté que définir manuellement l'emplacement est la seule option fiable dans certains cas plus complexes, lorsque le formulaire est automatiquement dimensionné et modifié dynamiquement.

Cependant, plutôt que de calculer les coordonnées manuellement, je suggérerais d'utiliser la méthode existante:

this.CenterToParent();
4
sherpa

J'ai trouvé une solution centrant la position de la fenêtre sans modèle sur la position du parent, la fenêtre enfant pouvant toujours être couverte par la fenêtre parent

f2.Show(f1);

qui définira le propriétaire de f2 sur f1, f2 s'affichera par-dessus le f1 en position centrale.

Ensuite, vous définissez

f2.Owner = null;

et voilà, f2 est une fenêtre séparée, avec la position de démarrage correcte.

3
Szybki

J'ai eu le même problème, je suis finalement allé avec ceci:

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

Utilisé comme:

MyForm form = new MyForm();
form.Show(this); // with or without

Le principal avantage est qu'il répond aux attentes de vos collègues, sans qu'il soit nécessaire de modifier le formulaire d'appel.

3
primo

La réponse de JYelton a fonctionné pour moi, mais le formulaire n'est centré que la première fois que Show () s'appelle . Si vous souhaitez masquer () le formulaire, puis le recentrer sur le parent à chaque fois que Show () est appelé, vous devez utiliser les éléments suivants dans votre formulaire:

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

Je me rends compte que c’est une vieille question, mais j’avais récemment le même problème et pour des raisons qui ne m’intéressent pas, je ne souhaitais pas utiliser la méthode form.ShowDialog () et mon application n’était pas un MDI application, la méthode CenterParent n’avait donc aucun effet. Voici comment j'ai résolu le problème en calculant les coordonnées du formulaire que je voulais centrer et en déclenchant le nouvel emplacement dans l'événement LocationChanged du formulaire principal. J'espère que cela aidera quelqu'un d'autre à avoir ce problème.

Dans l'exemple ci-dessous, le formulaire parent s'appelle MainForm et le formulaire que je veux centrer dans MainForm s'appelle 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;           
    } 

Si vous avez un formulaire parent redimensionnable et que vous souhaitez que votre sous-formulaire soit également centré chaque fois que le formulaire principal est redimensionné, vous devriez, en théorie, pouvoir placer ce code dans une méthode, puis appeler la méthode à la fois sur LocationChanged et SizeChanged. événements.

2
smitty1

En utilisant 

form.Show(this);

lève une exception si vous l'appelez une seconde fois. Définir manuellement l’emplacement semble être la seule option fiable:/(n’était-ce pas assez récemment que CenterParent fonctionnait auparavant?)

1
DanW

Peut-être que cela peut aider quelqu'un.

Form frmMessage = new Form();

Par expérience, même s’ils se ressemblent, ils se comportent différemment: 

Cette variante ne fonctionne pas:

if (frmMessage.Parent != null)
    frmMessage.CenterToParent();
else
    frmMessage.CenterToScreen();

Et cette variante fonctionne

if (frmMessage.Parent != null)
    frmMessage.StartPosition = FormStartPosition.CenterParent;
else
    frmMessage.StartPosition = FormStartPosition.CenterScreen;
1
Gogu CelMare

Une vieille question, je sais, mais j'avais le même problème mais pour une raison différente.

Le formulaire que j'ouvrais avait une méthode OnLoad remplacée:

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

mais n'appelait pas l'implémentation de base comme il se doit :

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

Lorsque vous substituez OnLoad (EventArgs) dans une classe dérivée, veillez à appeler la méthode OnLoad (EventArgs) de la classe de base afin que les délégués enregistrés reçoivent l'événement.

0
OffHeGoes

Petit changement à la réponse de 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.