Aplikacja MDI Co to takiego jest ta aplikacja MDI? OtóŜ w zasadzie w kaŝdej aplikacji występuje przynajmniej kilka okien umoŝliwiających wprowadzanie / wyświetlanie róŝnych danych. Okna te mogą być wyświetlane jako niezaleŝne od siebie, czyli jak gdyby odrębne programy, i wówczas kaŝde otwarte okno reprezentowane jest w pasku zadań Windows poprzez niezaleŝną ikonę, lub wyświetlane w ramach jednego okna głównego i wówczas wszystkie okna będące podrzędne do okna głównego są reprezentowane w pasku zadań przez jedną ikonę okna głównego. Taka aplikacja z jednym oknem głównym jest określana właśnie jako aplikacja MDI. W tym kursie przygotujemy właśnie takie okno główne aplikacji MDI. ZałoŜeniem całego kursu jest, Ŝe mamy zainstalowane środowisko VB.NET oraz najlepiej MS SQL Serwer lub ewentualnie MySQL albo Office Access. Cały kurs będzie realizowany w oparciu o MS SQL Serwer i będą tylko omawiane istotne róŝnice przy uŝywaniu innych baz danych (MySQL lub Access). W tym kursie na razie nie będziemy potrzebowali bazy danych. Uruchamiamy zatem środowisko VB.NET i tworzymy nowy projekt jak ilustruje to rysunek poniŝej: Rysunek 1. Tworzenie nowego projektu Informacje zawarte w ramce Recent Project lista projektów - są moŝliwe do modyfikacji poprzez edycję rejestru Windows. KaŜdy nowootwierany projekt jest dodawany do tej listy i w przypadku duŝej ich ilości część z nich jest tutaj niewidoczna. Aby zmienić kolejność ich
wyświetlania lub usunąć z tej listy projekty nieaktualne naleŝy zmodyfikować nazwy kluczy lub je usunąć z rejestru: HKEY_CURRENT_USER->Softvare->Microsoft->VBExpress->9.0->ProjectMRUList w przypadku VB.NET 2008 Express Po utworzeniu nowego projektu otworzy się w oknie głównym zakładka Form1.vb [Design] zawierająca projekt okna o nazwie Form1. Pierwsze, co robimy to zmieniamy nazwę tego okna w tym celu otwieramy zakładkę Properties po prawej stronie okna głównego i szukamy właściwości (Name) i wpisujemy tam nazwę okna, jaka będzie dostępna w kodzie programu (nie mylić z nazwą wyświetlaną w lewym górnym rogu samego okna jest to inna właściwość). Dla przykładu zamiast Form1 wpiszmy tam Glowne. Następnie odszukajmy właściwość Text i wpiszmy tam Okno główne aplikacji. Całość będzie wyglądała mniej więcej jak poniŝej: Rysunek 2. Okno aplikacji i jego właściwości Sugeruję aby w nazwach własnych obiektów (właściwość (Name) ) jak równieŝ w nazwach zmiennych w kodzie programu nie uŝywać polskich znaków diakrytycznych tak na wszelki wypadek, natomiast tam gdzie jest jakiś tekst do wyświetlenia (np. właściwość Text ) lub wartość zmiennej typu String w kodzie to jak najbardziej moŝna, a nawet naleŝy uŝywać polskich znaków. Teraz jeszcze pozostaje nam ustawienie podstawowej właściwości dla okna głównego aplikacji MDI, a mianowicie właściwość IsMdiContainer ustawiamy na Yes. Pozostałe właściwości, jakie moŝemy tutaj ustawić (tylko te bardziej istotne i mi znane ) to: ControlBox czy mają być wyświetlane przyciski umoŝliwiające minimalizację, maksymalizację rozmiaru okna i zamknięcie okna widoczne w prawym górnym rogu okna, Icon za pomocą tej właściwości moŝemy zmienić ikonę wyświetlaną w lewym górnym rogu okna z domyślnej systemowej na własną, Location połoŝenie lewego górnego rogu okna względem ekranu (tego w zasadzie nie zmieniamy nie ma potrzeby), Size rozmiar okna (tego teŝ w zasadzie nie zmieniamy będziemy to robić programowo), StartPosition startowe połoŝenie lewego górnego rogu okna względem ekranu ja prawie zawsze ustawiam tu wartość CenterScreen tak lubię, ale w tym wypadku ustawmy wartość Manual, WindowState jaki rozmiar ma przyjąć okno po uruchomieniu ( Normal takie jak wynika z właściwości Size, Minimized najmniejszy dopuszczalny rozmiar,
Maximized największy dopuszczalny rozmiar). Moglibyśmy tutaj ustawić wartość Maximized, aby okno wyświetliło się na cały ekran, ale zrobimy to programowo, więc pozostawmy wartość Normal. Po ustawieniu wszystkich niezbędnych właściwości powinniśmy uzyskać efekt mniej więcej jak poniŝej: Rysunek 3. Okno główne aplikacji MDI i jego właściwość Po tym wszystkim naleŝałoby zapisać projekt, aby cała nasza praca nie poszła na marne. Zapisu dokonujemy klikając ikonkę kilku dyskietek, Save all, co powoduje zapisanie wszystkich zmian na wszystkich zakładkach i sugeruję, aby w zasadzie zawsze uŝywać właśnie tej formy zapisu (przynajmniej na początku). JeŜeli wprowadzimy jakieś zmiany to na zakładce, na której dokonywaliśmy zmian pojawi się znak * na końcu jej nazwy oznacza on, Ŝe dane na tych zakładkach zostały zmienione i niezapisane. Przy pierwszym zapisie projektu pojawi się okno, w którym określamy gdzie dany projekt ma być zapisany: Rysunek 4. Pierwszy zapis nowego projektu Pole Name oznacza nazwę projektu, pole Location pełna ścieŝka dostępu do plików projektu. Pozostałe opcje na razie są nieistotne i zostawmy tak jak na rysunku. Mamy projekt zapisany, więc teraz przechodzimy do sedna, czyli pisania kodu. Aby to uczynić musimy otworzyć zakładkę z kodem danego okna ja zawsze robię to w ten sposób, Ŝe dwukrotnie szybko klikam na nagłówku okna i wówczas otwiera się okno z kodem i automatycznie utworzoną (choć pustą ) procedurą Load danego okna. Metoda alternatywna to otworzenie zakładki Solution Explorer zaznaczenie danego elementu projektu, który chcemy okodować i kliknięciu ikony View Code u góry zakładki.
Przed rozpoczęciem pisania kodu zmieńmy jeszcze nazwę pliku zawierającego nasze okno, a który nazywa się Form1.vb na zgodny z nazwą okna (choć nie musi być zgodny to jednak warto zachować taką właściwość aby potem wiedzieć, Ŝe dany plik zawiera dane odnośnie takiego to, a takiego okna) czyli Glowny. Robi się to klikając prawym klawiszem myszy na elemencie projektu identyfikującym nasze okno i wybierając opcję Rename i zmieniając nazwę na nową. Zmienioną nazwę zatwierdzamy klawiszem <Enter>: Rysunek 5. Zmiana nazwy pliku Po tym wszystkim zapiszmy projekt i przechodzimy do pisania kodu. Chcemy aby okno główne po otworzeniu zajmowało cały dostępny ekran (a rozmiar ekranu jest zaleŝny od ustawionej rozdzielczości, która moŝe być róŝna na róŝnych komputerach). W związku z tym wpisujemy w procedurze Glowne_Load następujący kod: Public Class Glowne Private Sub Glowne_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim wys, szer As Integer End Sub End Class wys = Screen.PrimaryScreen.WorkingArea.Height szer = Screen.PrimaryScreen.WorkingArea.Width Me.Height = wys Me.Width = szer Pierwsza linia zaczynająca się Dim oznacza definicję zmiennych lokalnych (czyli dostępnych tylko w obrębie danej procedury) jako zmienne typu Integer czyli liczby całkowite (bo w liczbach całkowitych jest rozmiar ekranu pikselach). Następnie pod zdefiniowane zmienne podstawiamy kolejno wysokość ekranu i szerokość ekranu. Dane te dostępne są w tzw. przestrzeni nazw o nazwie Screen, reszta występująca po nazwie Screen chyba nie wymaga komentarza. Po ustaleniu aktualnych wartości wysokości i szerokości bieŝącego ekranu przypisujemy te wartości do obiektu Me i odpowiednich jego
właściwości Height i Width czyli wysokości obiektu i szerokości obiektu. PoniewaŜ jesteśmy w klasie reprezentującej obiekt Główne a zatem reprezentującej nasze okno główne, więc obiekt Me oznacza w tym wypadku nasze okno główne. W innej klasie obiekt Me będzie reprezentował inne okno lub kontrolkę. PoniewaŜ się mocno napracowaliśmy z kodem to trzeba by zobaczyć co uzyskaliśmy, więc zapisujemy projekt i uruchamiamy ikonką Start Debugging i po chwili powinniśmy zobaczyć nasze okno zajmujące cały dostępny ekran. No dobrze okno się wyświetliło ale jest takie jakieś ubogie. Nie ma Ŝadnego menu jak w porządnej aplikacji, nie paska narzędziowego ani właściwie nic. Czas więc powrócić do projektowania okna i trochę je wzbogacić. Przechodzimy na zakładkę z widokiem okna, a następnie otwieramy zakładkę Toolbox. Odszukujemy komponent o nazwie MenuStrip, klikamy na nim raz lewym klawiszem myszki, następnie przesuwamy kursor nad nasze okno (kursor nad oknem zmieni wygląd na znaczek plusa z ikonką wybranego komponentu) i klikamy lewym klawiszem myszy w dowolnym miejscu okna co spowoduje dodanie komponentu MenuStrip1 do naszego okna czyli naszego menu: Rysunek 6. Dodanie komponentu MenuStrip do okna aplikacji Po dodaniu menu kliknijmy lewym klawiszem myszy w obszar oznaczony jako Type Here i wpiszmy tam Kursy : Rysunek 7. Dodawanie elementów menu
Następnie poniŝej wpiszmy Kurs 1 i poniŝej Kurs 2 (na razie wystarczy), następnie z boku po prawej wpiszmy Koniec. Całość po wpisaniu powinna wyglądać mniej więcej tak: Rysunek 8. Utworzone menu Po wpisaniu elementów menu kliknijmy kolejno na kaŝdym, otwórzmy zakładkę Properties i zmieńmy nazwę kaŝdego elementu menu. Nazwy elementów/komponentów mogą być dowolne jednak dobrze jest przyjąć jakąś konwencję nazewnictwa i się jej ściśle trzymać ułatwi to później nawigację po kontrolkach. Ja stosuję mniej więcej taką konwencję: najpierw dwu-, trzyliterowy skrót określający rodzaj kontrolki (np. dla ToolStripMenuItem mi, dla ComboBox cmb, dla kontrolki tekstowej txt itp. po czym następuje znak podkreślenia i wyraz określający cechę charakterystyczną danej kontrolki np. rodzaj przechowywanej danej czy w przypadku powyŝszych elementów menu wyświetlana nazwa (w przypadku wieloczłonowej nazwy elementu menu skracam to do jednego wyrazu) i tak np. element menu Kurs 2 nazywam mi_kurs2 itp. Rysunek 9. Zmiana nazwy elementów menu Następnie ponownie otwórzmy zakładkę Toolbox i odszukajmy komponent ToolStrip i przenieśmy go na nasze okno analogicznie jak robiliśmy to z menu. W nowoutworzonym elemencie kliknijmy znaczek grotu strzałki i z rozwiniętego menu wybierzmy SplitButton :
Rysunek 10. Tworzenie elementu paska narzędziowego Po utworzeniu elementu paska narzędziowego SplitButton rozwijalny przycisk ponownie rozwijamy menu w kolejnym elemencie i wybieramy Buton. Mamy teraz dwa elementy w pasku narzędziowym klikamy na pierwszy i w miejscu Type Here wpisujemy Kurs 1 i poniŝej Kurs 2 : Rysunek 11. Dodawanie kolejnych elementów do SplitButton Teraz klikamy element SplitButton i przechodzimy do zakładki Properties i ustawiamy następujące właściwości: (Name) nazwa komponentu, DisplayStyle wybieramy ImageAndText, Image moŝemy podać własną ikonkę danego elementu zamiast standardowej, Text wpisujemy Kursy, TextImageRelation wybieramy ImageAboveText. Właściwość ToolTipText określa tekst jaki pojawi się w chmurce gdy wskaźnik myszy będzie nad daną kontrolką. Dla kontrolek składowych elementu SplitButton wystarczy określić tylko właściwość (Name). Dla kolejnego elementu typu Buton określamy właściwości analogicznie jak dla SplitButton, gdzie właściwość Text podajemy Koniec. Jak widać elementy paska narzędziowego odpowiadają elementom menu choć oczywiście tak być nie musi i elementy paska narzędziowego mogą wskazywać inne czynności/działania niŝ elementy menu. Całość powinna wyglądać następująco:
Rysunek 12. Menu i pasek narzędziowy w głównym oknie aplikacji Po wprowadzeniu tych zmian zapisujemy projekt (jeŝeli jeszcze tego nie zrobiliśmy) i przystępujemy do wprowadzenia ostatniego elementu okna głównego. Otwieramy zakładkę Toolbox i wybieramy komponent StatusStrip i przenosimy na nasze okno analogicznie jak wcześniejsze. Na dole naszego okna pojawi się kontrolka paska stanu. Wybierzmy przez strzałkę trzy razy element StatusLabel, dla kaŝdego określmy właściwość (Name) i DisplayStyle na Text (moŝemy wybrać równieŝ ImageAndText ). W efekcie powinniśmy otrzymać okno jak poniŝej: Rysunek 13. Okno główne aplikacji Działaniem poszczególnych elementów menu Kursy, paska narzędziowego Kursy jak i paskiem stanu zajmiemy się w kolejnych kursach, a teraz oprogramujemy działanie elementu menu i paska narzędziowego - Koniec. Przechodzimy na zakładkę z kodem programu i z rozwijanego komponentu u góry wybieramy element menu Koniec, a komponentu po jego prawej stronie akcję Click. Operacja ta spowoduje utworzenie procedury dla zdarzenia Click dla obu tych elementów:
Rysunek 14. Utworzenie procedur związanych ze zdarzeniem Click komponentów Me.Close() Teraz w kaŝdej z procedur wpiszmy polecenie: lub Application.Exit() W tym przypadku oba polecenia są sobie równowaŝne poniewaŝ jesteśmy w oknie głównym aplikacji i jego zamknięcie (a to właśnie robią powyŝsze polecenia) spowoduje zamknięcie całej aplikacji. W przypadku okna podrzędnego polecenie Me.Close() spowoduje jedynie zamknięcie tego okna podrzędnego podczas gdy polecenie Application.Exit() spowoduje zamknięcie całej aplikacji taka jest róŝnica pomiędzy tymi poleceniami. I na koniec cały kod naszej aplikacji: Public Class Glowne Private Sub Glowne_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim wys, szer As Integer End Sub wys = Screen.PrimaryScreen.WorkingArea.Height szer = Screen.PrimaryScreen.WorkingArea.Width Me.Height = wys Me.Width = szer Private Sub mi_koniec_click(byval sender As Object, ByVal e As System.EventArgs) Handles mi_koniec.click Application.Exit() End Sub Private Sub tsi_koniec_click(byval sender As Object, ByVal e As System.EventArgs) Handles tsi_koniec.click Me.Close() End Sub End Class Zapisujemy teraz cały projekt i uruchamiamy go aby sprawdzić jak będzie wyglądał i działał:
Rysunek 15. Gotowa i uruchomiona aplikacja MDI W następnych kursach nieco rozbudujemy działanie menu, paska narzędziowego i paska stanu. Kolejny kurs będzie dotyczył łączenia się z bazą danych i odczytem pewnych informacji i ich prezentacją w oknie głównym.