2010-12-13 18 views
8

Zasadniczo mam dwa problemy z C# .NET MDI. Możesz pobrać rozwiązanie VS2010, które odtwarza błędy here.Program C# .NET MDI powoduje błędy w programowym ukrywaniu i wyświetlaniu zmaksymalizowanej formy potomnej, a po zmaksymalizowaniu ikona formularza dziecka nie może zostać zmieniona.

1) Kiedy programowo ukrywa i wyświetla ponownie zmaksymalizowaną dziecięcą formę, nie jest ona ponownie zmaksymalizowana prawidłowo i nie jest ani zmaksymalizowana, ani w normalnym stanie.

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

Kiedy forma dziecko jest zmaksymalizowane, a następnie programicaly ukrytych i pokazany ponownie, staje się coś takiego (proszę zauważyć pasek menu - pojawi się okno sterowania tworzą dziecka, ale forma dziecko nie jest zmaksymalizowane):

alt text

Na tym etapie forma dziecka nie może być przenoszona. Jednak znalazłem sposób na obejście tego problemu, po prostu pokazując i ukrywając fałszywą formę dziecka, która zmusza właściwą formę dziecka do zmaksymalizowania. Ale to powoduje, że obszar MDI migocze. Próbowano unieważnić, odświeżyć, zaktualizować metody, ale one nie pomagają. Być może są inne sposoby obejścia tego błędu i nie powodują migotania obszaru MDI z atrapą dziecka?

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

2) Gdy forma dziecka jest zmaksymalizowana, ikona formularza dziecka jest wyświetlana na pasku menu. Jeśli jednak musisz zmienić ikonę, gdy forma podrzędna jest zmaksymalizowana, ikona na pasku menu nie jest odświeżana (patrz obrazek powyżej). Znalazłem obejście tego, które zasadniczo ukrywa i pokazuje pasek menu. Ikona zostaje odświeżona, ale sprawia, że ​​wszystko poniżej paska menu migocze. Próbowano unieważnić, odświeżyć, zaktualizować metody, ale one nie pomagają. Czy jest jakiś inny sposób, aby pasek menu odświeżył ikonę formularza dziecka?

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

Również zauważyłem, że kiedy forma dominująca jest w normalnym trybie stanu okna (nie zmaksymalizowane) i zmienić szerokość lub wysokość postaci o 1 piksel, formularz dziecko zostanie zmaksymalizowane, jak powinno być i ikona formularza dziecka na pasku menu zostanie poprawnie odświeżona i nie potrzebujesz innego rozwiązania opisanego powyżej. Jeśli zmienię rozmiar formularza programowo, formularz miga o 1 piksel i nie mogę tego zrobić, gdy forma nadrzędna jest zmaksymalizowana. Czy istnieje sposób, w jaki mogę wywołać funkcję odświeżania/odświeżania, która jest wywoływana podczas zmiany rozmiaru formularza i która sprawia, że ​​forma dziecka jest odpowiednio zmaksymalizowana, a ikona na pasku menu odświeżona?

Odpowiedz

1

Znaleźliśmy sposób na obejście tych błędów.

Przede wszystkim należy zawiesić malowanie dla postaci i jej dzieci. Znalazłem bardzo pomocny wątek here, który opisuje, jak to zrobić.

Po zawieszeniu malowania należy wywołać metodę UpdateBounds kontrolki i zwiększyć szerokość lub wysokość ClientRectangle o jeden, a następnie zmniejszyć z powrotem do tej samej wartości, co wcześniej. Powoduje to wywołanie funkcjonalności układu, która powoduje, że wszystko jest aktualizowane/odświeżane. Ostatnim krokiem jest umożliwienie malowania. Niezbyt fajne rozwiązanie, ale to działa.

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

znajdę zawieszania malowanie bardzo pomocny nie tylko do pracy wokół tych dwóch błędów, ale także w ogóle do pracy GUI bardziej płynnie. Myślę, że to może pomóc w usunięciu wszelkiego rodzaju migotania. Jednak to rozwiązanie wymaga P/Invokes, co należy ogólnie unikać.

1

Czy jesteś zmęczony, używając opcji Ukryj/pokaż zamiast ustawiania widoczności na true/false?

Spróbuj:

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

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

Tak, próbowałem, ale nic się nie zmienia. Myślę, że childForm.Visible = true/false wywołuje te metody. – Povilas

+1

W rzeczywistości powinno być odwrotnie. Hide/Show powinien wtedy ustawić visible na false/true. –

1

Jest to błąd w realizacji wewnętrznego klasy MdiControlStrip, kontrola, który wyświetla ikonę i Min/Max/przywracania glifów w oknie nadrzędnym. Nie scharakteryzowałem jej jeszcze, kod nie jest taki łatwy. Klasycznym efektem ubocznym tego błędu jest to, że glify zostają podwojone, a Ty zauważyłeś inne efekty uboczne. Poprawka jest jednak prosta, opóźniając tworzenie okien potomnych do czasu zakończenia konstruktora. W ten sposób:

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

Ach, tak, użyłeś zdarzenia Load. Przesuń base.OnLoad() na dół. Działa na moim komputerze ™. –

+0

Wypróbowałem poprawkę, zastępując metodę OnLoad, ale zachowano to samo zachowanie. Nic się nie zmienia. Formy podrzędne muszą być tworzone dynamicznie, więc nie byłoby to dla mnie rozwiązaniem. – Povilas

1

Co z tym rozwiązaniem?

UPDATE

Właśnie dał ci pomysł, jak można zrobić. Lepszym rozwiązaniem wykorzystującym tę samą ideę, co powyżej, byłaby nowa forma bazowa, która zapisuje stan okna. Zobacz poniżej. Wyprowadź swoje formularze z FixedForm zamiast z Form:

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

Zdecydowanie jest to jedna z możliwości, jak przezwyciężyć błąd, ale sprawia, że ​​animacja postaci dziecka pojawia się w kółko, jest to dość irytujące. Moje obejście tego jest szybsze. – Povilas

+0

Sprawdź moją aktualizację rozwiązania bez migotania – Scoregraphic

+0

cóż, możesz wysłać wiadomość 'WM_SIZE' do uchwytu okna nadrzędnego, jeśli rozwiąże to problem. – Scoregraphic

0

Dlaczego nie po prostu ręcznie przywrócić wymaganą ikonę w pozycji MenuStrip, po utworzeniu okna:

menuStripMain.Items[0].Image = null;