2011-12-19 5 views
18

Nel seguente codice, solo il secondo metodo funziona per me (.NET 4.0). FormStartPosition.CenterParent non centra il modulo figlio sul relativo genitore. Perché?FormStartPosition.CenterParent non funziona

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

risposta

24

Questo perché non si sta dicendo che f2 sua controllante è.

Se si tratta di un'applicazione MDI, f2 deve avere MdiParent impostato su f1.

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

Se questo non è un'applicazione MDI, allora avete bisogno di chiamare il metodo ShowDialog utilizzando f1 come parametro.

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

noti che CenterParent non funziona correttamente con Show poiché non v'è alcun modo per impostare il genitore, quindi se ShowDialog volontà non è appropriato, l'approccio manuale è l'unica percorribile.

+5

esso non funziona anche se parli di chi è il suo genitore .. – nawfal

+1

Come posso fare questo? 'f2.Parent = f1;' non può essere compilato. Si prega di consultare la domanda SO di cui sopra, c'è un esempio di codice in cui il genitore non è impostato in modo esplicito e FormStartPosition.CenterParent funziona. – kol

+1

Bel tentativo, ma questa non è un'applicazione MDI :) Basta guardare il codice sopra: questo è l'intero programma, ed è chiaramente non MDI; e chiamo Show con f1; e questo è .NET 4. – kol

24

Se si imposta la titolare del form figlio in questo modo:

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

È quindi possibile centrare facilmente in questo modo:

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

Questa dovrebbe essere la risposta accettata IMO –

3

Ho trovato impostando la posizione è manualmente l'unica opzione affidabile in alcuni casi più complessi quando la forma viene ridimensionata automaticamente e modificata dinamicamente.

Tuttavia, piuttosto che calcolare le coordinate manualmente, suggerirei usando il metodo esistente:

this.CenterToParent(); 
+2

MSDN: "Non chiamare il metodo CenterToParent direttamente dal codice, ma impostare la proprietà StartPosition su CenterParent." http://msdn.microsoft.com/en-us/library/system.windows.forms.form.centertoparent.aspx – kol

+1

@kol Buon punto. Se l'impostazione di StartPosition è sufficiente, sicuramente questa è la strada da percorrere. Ma ci sono casi in cui non lo fa (ad esempio la dimensione cambia dinamicamente). Quindi questo è l'approccio manuale giusto, credo. – sherpa

3

ho trovato una soluzione che centrare la posizione della finestra non modale alla posizione del genitore, e la finestra bambino può essere ancora coperto da finestra genitore. Devi solo chiamare

f2.Show(f1); 

cui saranno definiti proprietario F2 per f1, f2 mostrerà il f1 al suo posizione centrale.

Dopodiché è impostato

f2.Owner = null; 

e ci si va, f2 è una finestra separata, con la posizione di avvio corretta.

+0

Questo non funziona. 'form.Show (proprietario)' non concentra la forma sul proprietario. – Dan

+0

Hai impostato form.StartPosition = CenterParent prima di chiamare form.Show (proprietario)? – Szybki

+0

Infatti, l'ho fatto. Ho provato sia via designer che via codice. Con e senza 'Owner = null', anche se onestamente non sono sicuro del perché ciò avrebbe alcun effetto. – Dan

1

Utilizzando

form.Show(this); 

genera un'eccezione se si chiama una seconda volta. L'impostazione manuale della posizione sembra essere l'unica opzione affidabile:/(non era abbastanza recente che CenterParent funzionasse?)

2

Mi rendo conto che questa è una domanda vecchia, ma di recente avevo lo stesso problema e per motivi Non ci arriverò, non volevo usare il metodo form.ShowDialog() e la mia applicazione non era un'applicazione MDI, quindi il metodo CenterParent non stava avendo alcun effetto.Ecco come ho risolto il problema, calcolando le coordinate per il modulo che volevo centrato e attivando la nuova posizione nell'evento LocationChanged del modulo principale. Speriamo che questo possa aiutare qualcun altro a risolvere questo problema.

Nell'esempio seguente, il modulo padre è denominato MainForm e il modulo che voglio centrato in MainForm si chiama 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 si dispone di un form padre ridimensionabile e si voleva la vostra forma secondaria per essere centrato ogni volta che il modulo principale viene ridimensionato, si dovrebbe, in teoria, essere in grado di inserire il codice in un metodo e quindi chiamare il metodo su entrambi gli eventi LocationChanged e SizeChanged.

7

sto usando questo codice dentro la mia principale forma, spero che aiuta: risposta

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

Infine, l'unica soluzione che funziona con C# nei moduli di vincita su VS2010. – Omzig

2

di JYelton lavorato per me, ma la forma è centrato solo la prima volta Show() è chiamato. Se si vuole nascondere() la forma, e poi lo hanno nuovamente centrato sul padre ogni volta Show() viene chiamato è necessario utilizzare il seguente nel modulo:

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

Ho avuto lo stesso problema, Alla fine ho andato con questo:

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

Usato come:

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

Il vantaggio principale è che si fa quello che i vostri colleghi e xpettarlo, senza richiedere alcun hack nel modulo di chiamata.

+1

Questo ha funzionato alla grande, grazie. Problema frustrante – user1003916

0

piccola modifica alla risposta di 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

Forse questo può aiutare qualcuno.

Form frmMessage = new Form(); 

Per esperienza, anche se sembrano simili, si comportano differenti:

Questa variante non funziona:

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

E questa variante funziona

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