it-swarm-pt.tech

FormStartPosition.CenterParent não funciona

No código a seguir, apenas o segundo método funciona para mim (.NET 4.0). FormStartPosition.CenterParent não centraliza o formulário filho sobre seu pai. Por quê?

Fonte: this SO pergunta

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

Isso é porque você não está dizendo f2 quem é Parent.

Se esta for uma aplicação MDI, então f2 deve ter sua MdiParent definida como f1.

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

Se este não for um aplicativo MDI, você precisará chamar o método ShowDialog usando f1 como o parâmetro.

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

Observe que CenterParent não funciona corretamente com Show, pois não há como definir a Parent, portanto, se ShowDialog não for apropriado, a abordagem manual é a única viável.

30
competent_tech

Se você definir o owner do formulário filho da seguinte forma:

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

Você pode centralizá-lo facilmente assim:

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

Estou usando esse código dentro do meu formulário principal, espero que ajude:

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

Descobri que definir a localização manualmente é a única opção confiável em alguns casos mais complexos quando o formulário é dimensionado automaticamente e modificado dinamicamente.

No entanto, em vez de calcular as coordenadas manualmente, sugiro usar o método existente:

this.CenterToParent();
4
sherpa

Eu encontrei uma solução que irá centralizar a posição da janela sem modelo para a posição do pai, e a janela filho ainda pode ser coberta pela janela pai. Você só precisa chamar

f2.Show(f1);

que irá definir o proprietário de f2 para f1, f2 mostrará a f1 na sua posição central.

Em seguida, você define

f2.Owner = null;

e lá vai você, f2 é uma janela separada, com a posição de inicialização correta.

3
Szybki

Eu tive o mesmo problema, eu finalmente fui com isso:

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

Usado como:

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

A principal vantagem é que ele faz o que seus colegas esperam que ele faça, sem exigir nenhum hack no formulário de chamada.

3
primo

A resposta de JYelton funcionou para mim, mas o formulário é centralizado apenas na primeira vez em que Show () é chamado. Se você quiser ocultar () o formulário e depois centrá-lo novamente no pai toda vez ) é chamado você precisa usar o seguinte no seu formulário:

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

Eu percebo que esta é uma pergunta antiga, mas eu estava recentemente tendo o mesmo problema e por razões que não entendo, eu não queria usar o método form.ShowDialog () e meu aplicativo não era um MDI application, portanto, o método CenterParent não estava tendo nenhum efeito. Foi assim que resolvi o problema, calculando as coordenadas do formulário que queria centralizado e acionando o novo local no evento LocationChanged do formulário principal. Espero que isso ajude alguém com esse problema.

No exemplo abaixo, o formulário pai é chamado MainForm e o formulário que eu quero centralizado no MainForm é chamado 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;           
    } 

Se você tiver um formulário pai redimensionável e quiser que seu subformulário também seja centralizado sempre que o formulário principal for redimensionado, você deve, em teoria, poder colocar esse código em um método e, em seguida, chamar o método em LocationChanged e SizeChanged eventos.

2
smitty1

Usando 

form.Show(this);

lança uma exceção se você ligar pela segunda vez. Definir manualmente a localização parece ser a única opção confiável:/(não foi bem recentemente que o CenterParent costumava funcionar?)

1
DanW

Talvez isso possa ajudar alguém.

Form frmMessage = new Form();

Pela experiência, embora pareçam semelhantes, eles se comportam de maneira diferente: 

Esta variante não funciona:

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

E essa variante funciona

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

Uma pergunta antiga, eu sei, mas tive o mesmo problema, mas por um motivo diferente.

O formulário que eu estava abrindo tinha um método OnLoad substituído:

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

mas não estava chamando a implementação base como deve fazer :

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

Ao substituir OnLoad (EventArgs) em uma classe derivada, certifique-se de chamar o método OnLoad (EventArgs) da classe base para que os representantes registrados recebam o evento.

0
OffHeGoes

Pequena alteração na resposta 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.