2011-12-19 26 views
18

En el siguiente código, solo el segundo método funciona para mí (.NET 4.0). FormStartPosition.CenterParent no centra el formulario secundario sobre su padre. ¿Por qué?FormStartPosition.CenterParent no funciona

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

Respuesta

24

Esto se debe a que no está diciendo f2 que es su Padre.

Si se trata de una aplicación MDI, entonces f2 debe tener su MdiParent establecido en f1.

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

Si esto no es una aplicación MDI, entonces tienes que llamar al método ShowDialog usando f1 como parámetro.

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

Tenga en cuenta que CenterParent no funciona correctamente con Show ya que no hay manera de establecer el Padre, así que si ShowDialog voluntad no es apropiada, el enfoque manual es la única viable.

+5

que no funciona incluso si menciona quién es su padre ... – nawfal

+1

¿Cómo podría hacer esto? 'f2.Parent = f1;' no se puede compilar. Consulte la pregunta SO que mencioné anteriormente, hay un ejemplo de código donde Parent no está establecido explícitamente, y FormStartPosition.CenterParent funciona. – kol

+1

Buen intento, pero esta no es una aplicación MDI :) Solo mire el código anterior: ese es el programa completo, y claramente no es MDI; y llamo Show con f1; y esto es .NET 4. – kol

24

Si se establece el propietario del formulario secundario de este modo:

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

continuación, puede centrar fácilmente así:

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

Esta debe ser la respuesta aceptada OMI –

3

encontré establecer la ubicación de forma manual es el único opción confiable en algunos casos más complejos cuando la forma es auto-dimensionada y modificada dinámicamente.

Sin embargo en lugar de calcular las coordenadas manualmente, me gustaría sugerir el uso de método existente:

this.CenterToParent(); 
+2

MSDN: "no llame al método CenterToParent directamente desde el código en su lugar, establecer la propiedad StartPosition a CenterParent." http://msdn.microsoft.com/en-us/library/system.windows.forms.form.centertoparent.aspx – kol

+1

@kol Buen punto. Si establecer la posición de inicio es suficiente, entonces este es el camino a seguir. Pero hay casos en los que no (por ejemplo, el tamaño cambia dinámicamente). Entonces este es el enfoque manual correcto, creo. – sherpa

3

he encontrado una solución que se centrará posición de la ventana modal a la posición de los padres, y la ventana niño puede ser todavía cubierta por ventana principal Sólo hay que llamar

f2.Show(f1); 

que establecerá propietario F2 a F1, F2 mostrará sobre la F1 en su posición central.

siguiente que establece

f2.Owner = null; 

y hay que ir, f2 es una ventana separada, con la posición de inicio correcta.

+0

Esto no funciona. 'form.Show (owner)' no centra el formulario en el propietario. – Dan

+0

¿Ha establecido form.StartPosition = CenterParent antes de llamar a form.Show (owner)? – Szybki

+0

De hecho, lo hice. Intenté ambos a través del diseñador y el código. Con y sin 'Owner = null', aunque honestamente no estoy seguro de por qué eso tendría algún efecto. – Dan

1

Usando

form.Show(this); 

lanza una excepción si se llama a una segunda vez. Configurar manualmente la ubicación parece ser la única opción confiable:/(¿no fue bastante recientemente que CenterParent solía funcionar?)

2

Me doy cuenta de que esta es una vieja pregunta, pero recientemente tuve el mismo problema y por razones No entraré, no quería usar el método form.ShowDialog() y mi aplicación no era una aplicación MDI, por lo tanto, el método CenterParent no estaba teniendo ningún efecto.Así es como resolví el problema, calculando las coordenadas de la forma que quería centrada y activando la nueva ubicación en el evento LocationChanged del formulario principal. Espero que esto ayude a alguien más a tener este problema.

En el ejemplo siguiente, el formulario principal se llama MainForm y el formulario que quiero centrado en MainForm se llama 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 usted tiene un formulario principal de tamaño variable y que quería que su sub formulario también se centra cada vez que se cambia el tamaño del formulario principal, que debería, en teoría, ser capaz de colocar este código en un método y luego llamar a la método en los eventos LocationChanged y SizeChanged.

7

Estoy usando este código dentro de mi forma principal, espero que ayude: Respuesta

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

Finalmente, la única solución que funciona para C# en formularios ganadores en VS2010. – Omzig

2

de JYelton trabajó para mí, pero la forma se centra únicamente la primera vez Show() se llama. Si desea ocultar() la forma, y ​​luego tener que re-centra en el padre cada vez que Show() se llama necesita usar lo siguiente en el formulario:

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

que tenían el mismo problema, Al final fuimos con esto:

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

se utiliza como:

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

La principal ventaja es que hace lo que su colegas correo Espere que lo haga, sin requerir ningún hack en el formulario de llamada.

+1

Esto funcionó muy bien, gracias. Problema frustrante – user1003916

0

pequeño cambio en la respuesta 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); 
} 
1

Tal vez esto puede ayudar a alguien.

Form frmMessage = new Form(); 

Por experiencia, a pesar de que parecen similares, se comportan diferente:

Esta variante no funciona:

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

Y esta variante funciona

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