Aplikacja wielookienkowa
Aplikacja wielookienkowa może pracować w dwóch trybach:
- w trybie okna nadrzędnego i wielu okien potomnych umieszczonych na pulpicie środowiska Windows
- w trybie okna nadrzędnego i wielu okien potomnych umieszczonych wewnątrz okna nadrzędnego
Rodzaj trybu pracy aplikacji wielookienkowej zależy od tego czy wartość this.IsMdiContainer formatki okna nadrzędnego ustawimy na true. Możemy to zrobić w oknie właściwości tworzonej formatki okna (wygodniejsze rozwiązanie), lub w kodzie programu w momencie ładowania głównego okna (zdarzenie Load)
private void Form1_Load(object sender, EventArgs e)
{
this.IsMdiContainer = true;
}
Cel: Napisz aplikację wielookienkową zawierającą menu, z którego można otwierać nowe okna.

Krok 1. Układ komponentów
- MenuStrip- sztuk 1
- Form- sztuk co najmniej 3
Uwaga: Komponent Form nie jest dostępny w oknie Przybornika. Nowy formularza (klasa Form) dodaję się z menu Projekt/ Dodaj formularz Windows Forms
Krok 3. Ustalamy nadrzędną formatkę- okno główne
W aktywnej formatce we właściwościach okna wybieramy opcję kontenera MDI (IsMdiContainer ustawiamy na True)

Krok 3. Dodajemy nowe formatki okien
Przechodzimy do opcji Projekt głównego menu środowiska Visual Studio i wybieramy opcję Dodaj formularz Windows Forms
W otrzymanym oknie dialogowym wykonujemy poniższe czynności

Nazwę można zmienić (nie wolno używać spacji), ale wygodniej jest zachować proponowaną.
Czynności powtarzamy dla wszystkich dodawanych okien w tworzonej aplikacji. Prawidłowo wykonanie tego kroku powinno dać widok kolejnych formularzy formatek okien

Krok 4. Tworzymy menu okna głównego
Menu okna głównego posłuży nam do otwierania kolejnych okien. Dodatkowo przypiszemy im klawisze skrótu. W obszarze okna głównego osadzamy komponent MenuStrip i tworzymy menu

Dodanie klawiszy skrótów opcjom menu wykonujemy we właściwościach aktywnego ToolStripMenuItem tak jak pokazuje to poniższa ilustracja

Efekt końcowy przypisanych klawiszy skrótów przedstawi się jak poniżej

Krok 5. Deklaracja zmiennych okien formatek
Do dalszych przewidywanych celów projektowych działania aplikacji wielookienkowej zmiennym nadamy charakter publiczny
public partial class Form1 : Form
{
public Form2 form2;
public Form3 form3;
public Form4 form4;
public Form1()
{
Krok 6. Wywołanie okna formatki
Jest kilka możliwości rozwiązania utworzenia okna formatki podrzędnej tak zwanego dziecka okna głównego. Wybór metody rozwiązania będzie wpływać na sposób przesyłania danych pomiędzy oknami. Poniżej przedstawię sposób otwarcia jednego konkretnego okna z jednoczesnym zabezpieczeniem przed wielokrotnym powieleniem. Zdarzenie będzie obsługiwane w metodzie Click komponentu ToolStripMenuItem
private void Okno1ToolStripMenuItem_Click(object sender, EventArgs e)
{
//otwarcie jednego konkretnego okna
//zabezpiecz przed wielokrotnym powielaniem tworzenia okna
if (form2 == null)
{
form2 = new Form2();
form2.MdiParent = this;
form2.Tag = "okno1";
form2.FormClosed += new FormClosedEventHandler(zwolnijUchwyt);
form2.Show();
}
else form2.Activate();
}
Uwaga. Powyższa metoda zawiera nadpisanie standardowej funkcji zamykającej FormClosed. Jest to konieczne, ponieważ musimy zwolnic uchwyt do zmiennej reprezentującej okno. Jeżeli byśmy tego nie zrobili, to powyższe rozwiązanie zadziałałoby jeden raz, dopóki byśmy nie zamknęli wywołanego okna dziecka w działającej aplikacji.
Postać funkcji, którą musimy nadpisać ma postać (przewidujemy rozwiązanie uniwersalne dla wszystkich utworzonych podokien wywołanych tą metodą):
public void zwolnijUchwyt(object sender, FormClosedEventArgs e)
{
Form f =sender as Form;
switch (f.Tag.ToString())
{
case "okno1": form2 = null; break;
case "okno2": form3 = null; break;
case "okno3": form4 = null; break;
}
}
Skompiluj i uruchom aplikację sprawdzając jej działanie.
Krok 7. Uniwersalne wywołanie okna dla metody pierwszej
Zastosowanie uniwersalnej funkcji skraca kod programu. Kod funkcji, którą będziemy mogli zastosować dla dowolnego okna musi zawierać dwa parametry- argumenty. Parametr klasy Form i parametr łańcucha znaków string dla właściwości Tag tworzonego okna.
void RobOkno(Form f, string tag)
{
f.MdiParent = this;
f.Tag = tag;
f.FormClosed += new FormClosedEventHandler(zwolnijUchwyt);
f.Show();
f.Activate();
}
Użycie powyższej funkcji w obsłudze komunikatu zdarzenia Click (dopinamy je we właściwościach w metodzie Click komponentu ToolStripMenuItem) jest następujące
private void Okno2ToolStripMenuItem_Click(object sender, EventArgs e)
{
//zabezpiecz przed wielokrotnym powielaniem tworzenia okna
if (form3 == null) RobOkno(form3 = new Form3(), "okno2");
else form3.Activate();
}
Skompiluj program i sprawdź efekt działania. Prawidłowo działająca na tym etapie aplikacja pozwoli na wielokrotne otwieranie i zamykanie okien dzieci. Przedstawia to poniższa ilustracja

Metoda II wywołania okien w aplikacji wielookienkowej
Ta metoda opiera się na zastosowaniu instancji do klasy okna dziecka. Nie wymaga nadpisywania zdarzenia zamknięcia okna. Zwolnienie uchwytu instancji wykonuje się w każdym oknie z osobna w metodzie FormClosed
Krok 1. Rozbudowanie opcji menu
Menu głównego okna należy rozbudować o kolejne opcje

Krok 2. Dodajemy kolejne formatki okien dzieci
Powtarzamy czynności z kroku 3 metody I
Krok 3. Deklarujemy instancję klasy okna oraz funkcję zwracającą uchwyt do klasy okna
Zmienna instancji klasy musi być prywatna, a funkcja ją zwracająca publiczna. Obie muszą być statyczne, co dla kompilatora oznacza, że nie będą nadpisywane w dalszym rozwijaniu kodu .projektu. Każda nowo dodana klasa okna dziecka powinna zawierać ten kod
public partial class Form7 : Form
{
private static Form7 instancja;
public static Form7 Instancja
{
get{
if (instancja == null) instancja = new Form7();
return instancja;
}
}
Krok 4. Zwolnienie uchwytu instancji
Zwolnienie uchwytu instancji wykonuje się w każdym oknie z osobna w metodzie FormClosed
private void Form7_FormClosed(object sender, FormClosedEventArgs e)
{
instancja = null;
}
Kompilacja programu na tym etapie nie pozwoli otworzyć dodanych okien ale umożliwi sprawdzenie czy kod nie zawiera błędów
Krok 5. Uniwersalna funkcja tworząca instancję okna
Przechodzimy do zakładki kodu formatki okna głównego. Tworzymy dwuargumentową funkcję tworząca okno dziecka
void RobOknoInstancji(Form f,string tag)
{
f.MdiParent = this;
f.Tag = tag;
f.Show();
f.Activate();
}
Zwróć uwagę, że ciało funkcji nie zwiera warunku zabezpieczającego przed wielokrotnym konstruowaniem tego samego okna dziecka. Warunek ten już został w prowadzony w publicznej statycznej funkcji Instancja w kodzie każdej tak dodawanej formatki.
Krok 6. Wywołanie okna poprzez instancję klasy
Użycie powyższej funkcji wymaga obsługę komunikatu zdarzenia Click (dopinamy je we właściwościach w metodzie Click komponentu ToolStripMenuItem)
private void OknoInstancja3ToolStripMenuItem_Click(object sender, EventArgs e)
{
RobOknoInstancji(Form7.Instancja, "OknoInstnacj3");
//przykład wypełnienia wlasciwosci Text instancji nowego okna
Form7.Instancja.Text = "Okno Instancji 3";
Form7.Instancja.Width = this.Width / 2;
Form7.Instancja.Height = this.Height / 2;
}
Powyższa funkcja zawiera kilka przykładowych odwołań do podstawowych właściwości wywołanych okien dzieci.
Po skompilowaniu i uruchomieniu projektu prawidłowo działająca aplikacja wygląda jak poniżej
