2010-12-13 33 views
8

Fondamentalement, j'ai deux problèmes avec C# .NET MDI. Vous pouvez télécharger la solution VS2010 qui reproduit les bugs here.Bogues C# .NET MDI lors du masquage par programme et affichage à nouveau d'un formulaire enfant maximisé et lorsqu'il est agrandi, l'icône de la forme enfant ne peut pas être modifiée

1) Lorsque vous masquez et affichez à nouveau une forme enfant agrandie, elle n'est pas agrandie correctement de nouveau et ne devient ni agrandie ni dans un état normal.

childForm = new Form(); 
childForm.Text = "Child Form"; 
childForm.MdiParent = this; 

... 

private void showButton_Click(object sender, EventArgs e) 
{ 
    childForm.Visible = true; 
} 

... 

private void hideButton_Click(object sender, EventArgs e) 
{ 
    childForm.Visible = false; 
} 

Lorsque formulaire enfant est maximisée, puis programicaly caché et montré à nouveau, il devient quelque chose comme ça (s'il vous plaît noter la barre de menu - boîte de commande de formulaire enfant apparaît, mais sous forme d'enfant n'est pas maximisé):

alt text

À ce stade, la forme de l'enfant ne peut pas être déplacée. Cependant, j'ai trouvé une solution de contournement pour cela, simplement en montrant et en cachant un formulaire enfant fictif, qui force la forme réelle de l'enfant à être correctement maximisée. Mais cela fait scintiller la zone MDI. Essayé Invalider, Actualiser, Mettre à jour les méthodes, mais ils n'aident pas. Peut-être qu'il existe d'autres solutions de contournement pour surmonter ce bug et ne pas faire scintiller la zone MDI avec une forme enfant fictive?

private void workaround1Button_Click(object sender, EventArgs e) 
{ 
    dummyForm.Visible = true; 
    dummyForm.Visible = false; 
} 

2) Lorsque la forme enfant est agrandie, l'icône du formulaire enfant est affichée dans la barre de menus. Toutefois, si vous devez modifier l'icône pendant que le formulaire enfant est agrandi, l'icône de la barre de menus n'est pas actualisée (voir l'image ci-dessus). J'ai trouvé une solution de contournement pour cela aussi, qui cache essentiellement et montre la barre de menu. L'icône est rafraichie, mais cela fait clignoter tout ce qui se trouve sous la barre de menu. Essayé Invalider, Actualiser, Mettre à jour les méthodes, mais ils n'aident pas. Existe-t-il un autre moyen de créer une barre de menus pour actualiser l'icône du formulaire enfant?

private void workaround2Button_Click(object sender, EventArgs e) 
{ 
    menuStrip.Visible = false; 
    menuStrip.Visible = true; 
} 

Aussi je remarqué que lorsque le formulaire parent est en mode normal de l'état de la fenêtre (non maximisée) et que vous modifiez la largeur ou la hauteur de la forme par 1 pixel, sous forme d'enfant devient maximisée comme il devrait être et l'icône de la forme enfant sur la barre de menu est rafraichie correctement et vous n'avez pas besoin d'autre solution de contournement que j'ai décrite ci-dessus. Si je change la taille de la forme programicaly, forme le scintillement de 1 pixel et je ne peux pas faire cela, quand la forme parent est maximisée. Existe-t-il un moyen d'invoquer la fonctionnalité repaint/refresh qui est appelée lorsque vous redimensionnez un formulaire et qui rend la forme enfant maximisée correctement et l'icône de la barre de menu actualisée?

Répondre

1

Vous avez trouvé un moyen de contourner ces bogues.

Tout d'abord vous devez suspendre la peinture pour un formulaire et ses enfants. J'ai trouvé un fil très utile here, qui décrit comment le faire. Après avoir suspendu la peinture, vous devez appeler la méthode UpdateBounds du contrôle et augmenter la largeur ou la hauteur de ClientRectangle d'un, puis la réduire à la même valeur que précédemment. Cela appelle la fonctionnalité de mise en page qui fait tout pour mettre à jour/repeindre. La dernière étape consiste à permettre la peinture. Je ne pense pas que ce soit une très belle solution, mais cela fonctionne.

StopDrawing(); 
UpdateBounds(Location.X, Location.Y, Width, Height, ClientRectangle.Width, ClientRectangle.Height + 1); 
UpdateBounds(Location.X, Location.Y, Width, Height, ClientRectangle.Width, ClientRectangle.Height - 1); 
StartDrawing(); 

je trouve très utile de suspendre la peinture non seulement pour travailler autour de ces deux bugs, mais aussi en général pour rendre le travail graphique plus en douceur. Je suppose que cela peut aider à éliminer toute sorte de scintillement. Cependant, cette solution nécessite P/Invokes, ce qui devrait être évité en général.

1

Avez-vous fatigué en utilisant Hide/Show au lieu de mettre le paramètre visible à true/false?

Essayez:

private void showButton_Click(object sender, EventArgs e) 
{ 
    childForm.Show(); 
} 

private void hideButton_Click(object sender, EventArgs e) 
{ 
    childForm.Hide(); 
} 
+0

Oui, j'ai essayé, mais rien ne change. Je pense que childForm.Visible = true/false appelle ces méthodes. – Povilas

+1

En fait, il devrait être l'inverse. Cacher/Montrer devrait alors rendre visible à faux/vrai. –

1

Il y a un bug dans la mise en œuvre de la classe MdiControlStrip interne, le contrôle qui affiche l'icône et les min/max/restauration dans la fenêtre Glyphes mère. Je ne l'ai pas encore caractérisé, le code n'est pas si facile. Un effet secondaire classique du bug est que les glyphes sont doublés, vous avez trouvé d'autres effets secondaires. Le correctif est simple, retarder la création des fenêtres enfants jusqu'à la fin du constructeur. Comme ceci:

public MainForm() 
    { 
     InitializeComponent(); 
    } 
    protected override void OnLoad(EventArgs e) { 
     childForm = new Form(); 
     childForm.Text = "Child Form"; 
     childForm.MdiParent = this; 

     dummyForm = new Form(); 
     dummyForm.MdiParent = this; 
     dummyForm.WindowState = FormWindowState.Maximized; 
     base.OnLoad(e); 
    } 
+0

Ah, oui, vous avez utilisé l'événement Load. Déplacez base.OnLoad() vers le bas. Fonctionne sur ma machine ™. –

+0

Essayé votre correctif en remplaçant la méthode OnLoad, mais le même comportement buggé reste. Rien ne change. Et les formulaires enfants doivent être créés dynamiquement, donc ce ne serait pas vraiment une solution pour moi. – Povilas

1

Que pensez-vous de cette solution de contournement?

MISE À JOUR

Je viens de vous donner l'idée que vous pourriez faire. Une meilleure solution utilisant la même idée que ci-dessus serait une nouvelle forme de base qui sauve l'état des fenêtres. Voir ci-dessous. Dérivez vos formulaires de FixedForm au lieu de Formulaire:

public partial class FixedForm : Form 
{ 
    private FormWindowState lastWindowState; 

    public FixedForm() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnVisibleChanged(EventArgs e) 
    { 
     base.OnVisibleChanged(e); 

     if (Visible) 
     { 
      WindowState = lastWindowState; 
     } 
     else 
     { 
      lastWindowState = WindowState; 
      WindowState = FormWindowState.Normal; 
     } 
    } 
} 
+0

Certainement c'est l'une des possibilités pour surmonter le bug, mais cela permet de maximiser l'animation de la forme enfant à apparaître encore et encore, c'est un peu ennuyeux. Ma solution de contournement est plus rapide. – Povilas

+0

Vérifiez ma mise à jour pour une solution sans scintillement – Scoregraphic

+0

bien, vous pouvez envoyer un message 'WM_SIZE' à la poignée de la fenêtre parente si cela résout le problème. – Scoregraphic

0

Pourquoi ne pas simplement réinitialiser manuellement l'icône requise dans les éléments MenuStrip, après la création de la fenêtre:

menuStripMain.Items[0].Image = null;