Kolejny wykład w cyklu Akademii PC Kuriera poświęconej programowaniu w Visual Basic.NET rozpoczniemy od kontynuacji opisu znaczenia i roli zdarzeń w aplikacji. Z pierwszego odcinka uważny czytelnik zapamiętał z pewnością, że zdarzenia to działania, jakie zachodzą na danym obiekcie. Programowanie bazujące na zdarzeniach polega na dostarczeniu kodu programu, który ma zostać wykonany jako reakcja na zajście zdarzenia. Kod ten zawarty jest w tzw. procedurze obsługi zdarzenia (ang. event-handler). Przykładowe zdarzenia, jakie eksponuje obiekt formularza prezentuje tabela: Zdarzenie Zachodzi gdy Activated w efekcie działania użytkownika lub wykonania kodu formularz staje się aktywnym oknem aplikacji Click kliknięto na formularzu Closed Po zamknięciu okna formularza naskutek działania użytkownika lub wywołania metody Close formularza Closing formularz jest zamykany Deactivate formularz przestaje być aktywnym oknem w aplikacji Got Focus element formularza zostaje podświetlony (otrzymuje fokus) Load formularz jest wyświetlany po raz pierwszy Jeśli na formularzu znajduje się obiekt (np. przycisk) zdarzenie GotFocus nie zachodzi. Ponieważ tylko jeden obiekt w aplikacji może być podświetlony, system Windows w momencie wyświetlania okna aplikacji zawierającego obiekt automatycznie nadaje fokus temu obiektowi. Aby obsłużyć zdarzenie związane z przełączeniem się do lub z aktywnego okna należy więc dostarczyć odpowiedni kod obsługi dla zdarzenia Activated lub Deactivate (wyjaśnienie dla zaawansowanych programistów: zdarzenia GotFocus oraz LostFocus związane są z komunikatami WM_KILLFOCU oraz WM_ETFOCU, wywoływanymi w czasie aktualizacji UICues, czyli aktualizacji stanu interfejsu użytkownika). Kolejność zdarzeń Jak wynika z tabeli, każdy obiekt dysponuje zazwyczaj co najmniej kilkoma zdarzeniami. Co się jednak dzieje, gdy niektóre z działań użytkownika lub kodu powodują wywołanie kilku zdarzeń? Jakie zdarzenie zajdzie, gdy użytkownik otworzy nowe okno aplikacji i przełączy się na nie: Load, Activated, Got Focus? Czy jest to jedno zdarzenie czy też osobne? A jeśli osobne, to czy zachodzą one jednocześnie w tym samym momencie? Odpowiedź jest prosta zajdą wszystkie te zdarzenia, ale pojedynczo wg z góry ustalonej i niezmiennej kolejności. Przykładowo zdarzenie Load formularza zawsze zachodzi przed zdarzeniem Activated. Znajomość kolejności zachodzenia zdarzeń jest istotna, bo kolejność zdarzeń określa kolejność wykonywania się kodu w aplikacji. Należy zapamiętać, że na wystąpienie niektórych ze zdarzeń mają wpływ wartości, jakie przypisano własnościom. Tabela pokazuje kolejność zdarzeń związanych z podświetleniem obiektu w aplikacji: Kolejność Zdarzenie Opis 1 Enter Obiekt staje się aktywny (uwaga: w przypadku obiektu formularza zamiast zdarzenia Enter występuje zdarzenie Activated), ale jeszcze nie podświetlony 2 GotFocus Obiekt został podświetlony 3 Leave Żądanie zmiany fokusa aplikacji z bieżącego obiektu na inny obiekt 4 Validating Przed opuszczeniem fokusa obiekt na wykonać dodatkowe działanie najczęściej działaniem tym jest walidacja wprowadzonych przez użytkownika danych (np. w polu tekstowym). Uwaga zdarzenie zachodzi jedynie wtedy, gdy własność CausesValidation jest równa True. 5 Validated Zachodzi w momencie zakończenia działania procedury sprawdzającej poprawność wprowadzonych danych. Podobnie jak w przypadku
zdarzenia Validating, zdarzenie Validated zachodzi pod warunkiem, że własność CausesValidation jest równa True. 6 LostFocus Fokus został przełączony z bieżącego obiektu na inny obiekt. W przypadku stosowania obiektów, mogących zawierać inne obiekty (np. obiekt GroupBox) zdarzenia Enter i Leave przekazywane są zgodnie z hierarchią i przechodzą w górę i w dół, aż do osiągnięcia odpowiedniego obiektu. Nie zaleca się zmiany aktywnego obiektu w aplikacji poprzez kod umieszczony w procedurze obsługi zdarzenia LostFocus. Może to być powodem zawieszenia się aplikacji lub systemu operacyjnego (zainteresowane osoby odsyłam do tematów związanych z komunikatem WM_KILLFOCU, kolejkami zdarzeń (Message Queues) oraz zakleszczeń komunikatów (Message Deadlocks). Procedura obsługi zdarzenia Procedura obsługi zdarzenia (ang. event-handler) to fragment kodu, który zostanie wykonany w momencie zajścia zdarzenia. Kod ten umieszcza się w procedurach ub (procedury i funkcje zostaną dokładnie omówione w jednym z kolejnych odcinków Akademii PC Kuriera). Każda z procedur obsługi zdarzeń musi mieć nazwę (sygnaturę), określoną zgodnie z konwencją przyjętą w Visual Basic.NET. Konwencja ta określa, że nazwa procedury obsługi zdarzenia składa się z nazwy obiektu wysyłającego informację o zajściu zdarzenia, znaku podkreślenia (_) oraz nazwy zdarzenia. Przykładowym nagłówkiem procedury obsługi zdarzenia Click formularza Form1 jest więc Form1_Click. Uwaga: Osoby mające doświadczenie w programowaniu w Visual Basic 6 dostrzegą pewnie różnice pomiędzy procedurami obsługi zdarzeń formularza w obu wersjach języka. W Visual Basic 6 wszystkie zdarzenia formularza składały się ze słowa Form, znaku podkreślenia oraz nazwy zdarzenia (np.form_click). W Visual Basic.NET położono duży nacisk na ujednolicenie języka. Visual tudio.net ułatwia proces tworzenia kodu. Programista nie musi pamiętać nazw wszystkich zdarzeń, jakie udostępnia obiekt. Procedurę kodu obsługi zdarzenia można utworzyć dwojako: W otwartym edytorze formularza kliknąć dwukrotnie na danym obiekcie. powoduje to otwarcie okna edytora kodu oraz automatyczne utworzenie szkieletu procedury obsługi domyślnego zdarzenia, które posiada każdy z obiektów, z jakich buduje się interfejs użytkownika. Przykładowo dla formularza zdarzeniem tym jest Load, natomiast dla przycisku - Click. tworzyć edytor kodu poprzez kliknięcie w oknie olution Explorer na ikonie View Code (należy pamiętać, że aktywną formą powinna być forma, dla której chcemy dostarczyć kod). powoduje to otwarcie okna edytora kodu. rys. 1 Okno olution Explorer oraz wyróżniona ikona View Code W otwartym oknie edytora kodu należy teraz skorzystać z dwóch list rozwijanych:
ClassName listy zawierającej nazwy wszystkich obiektów formularza oraz samego formularza, służącej do ustalenia kontekstu obiektu tworzonej procedury obsługi zdarzenia. Z listy tej należy wybrać (Base Class Events) w przypadku tworzenia procedury obsługi zdarzenia formularza lub nazwę obiektu (np. Button1), jeśli tworzymy kod obsługi zdarzenia dla obiektu, jaki ten formularz zawiera. MethodName po ustaleniu kontekstu obiektu (poprzez odpowiedni wybór z listy ClassName) z listy zawierającej nazwy wszystkich zdarzeń eksponowanych przez obiekt, należy wybrać konkretne zdarzenie. Oba sposoby spowodują utworzenie poprawnego szkieletu procedury obsługi zdarzenia. Programiście pozostaje jedynie uzupełnić ciało procedury obsługi zdarzenia o kod zapewniający odpowiednią funkcjonalność: Private ub Form1_Load(ByVal sender As ystem.object, ByVal e As ystem.eventargs) Handles MyBase.Load End ub Uwaga: linie 1 i 2 powyższego kodu należy umieścić w jednym wierszu. Ćwiczenie Utwórzmy prostą aplikację złożoną z jednego formularza. W momencie kliknięcia użytkownika na formularzu, aplikacja powinna się zamykać, sygnalizując ten fakt dźwiękiem. Do realizacji powyższego zadania wykorzystamy metodę Close(),polecenie Beep oraz zdarzenie Click. Metoda postępowania: Utwórz nowy projekt Visual Basic.NET, skorzystaj z szablonu Windows Application Jeśli okno olution Explorer jest zamknięte, otwórz je korzystając z menu View oraz polecenia olution Explorer W oknie olution Explorer kliknij na ikonie View Code, aby przełączyć się do okna edytora kodu Z listy rozwijanej ClassName wybierz (Base Class Events) ( tworzymy szkielet procedury obsługi zdarzenia) Z listy rozwijanej Method Name wybierz zdarzenie Click. Zwróć uwagę, że szkielet procedury obsługi zdarzenia został utworzony. Uzupełnij ciało procedury obsługi zdarzenia. Pomiędzy linie Private ub Form1_Click() oraz End ub wprowadź: o Beep () o Me.Close() Cała procedura obsługi zdarzenia powinna być następująca: Private ub Form1_Click(ByVal sender As Object, ByVal e As ystem.eventargs) Handles MyBase.Click Beep() Me.Close() End ub Uwaga: linię 1 i 2 w powyższym kodzie należy zapisać w jednym wierszu Uruchom aplikację korzystając z przycisku tart na standardowym pasku narzędzi. Kliknij na formularzu, aby sprawdzić działanie aplikacji.okna modalne i niemodalne Aplikacja może dysponować więcej niż jednym oknem. Każde z okien może zostać wyświetlone w sposób modalny lub niemodalny. Przykładem okna modalnego jest dowolne okno dialogowe. W momencie wyświetlenia okna modalnego użytkownik może korzystać tylko i wyłącznie z tego okna.
Jeśli aplikacja dysponuje innymi otwartymi oknami, użytkownik nie może wykonać na nich jakichkolwiek działań (zamknąć, przesunąć, itd. itp.) bez uprzedniego zamknięcia okna modalnego.. Uwaga: Aplikacja może wyświetlić tylko jedno modalne okno na raz. Okna niemodalne pozwalają użytkownikowi na większą swobodę niż okna modalne. Użytkownik w każdej chwili może przełączyć się z aktywnego okna, może każde z takich okien przesunąć czy też skorzystać z jego funkcjonalności bez konieczności zamykania pozostałych otwartych okien. Domyślnie wszystkie wyświetlane okna są niemodalne. Aby wyświetlić okno modalnie, należy skorzystać z metody howdialog formularza (które pełni rolę okna modalnego). Interakcje modalne wykorzystywane są do wymuszenia na użytkowniku określonego działania, gdy jego zakończenie warunkuje rozpoczęcie kolejnego zadania. Interakcje niemodalne zapewniają użytkownikowi większą swobodę działań, gdyż w każdym momencie może on rozpocząć lub kontynuować inne działania, po czym może powrócić do realizacji zadania bieżącego. Wydaje się, że ze względu na wspomnianą swobodę użytkownika w aplikacji powinny przeważać interakcje modalne, choć ich liczba powinna zostać ograniczona do niezbędnego minimum. Zmniejsza to ryzyko rozpoczęcia przez użytkownika wielu działań, i późniejszego zagubienia się w logice aplikacji lub procesu. Minimum interakcji modalnych zapewnia więc użytkownikowi większą kontrolę nad aplikacją. Zarządzanie formularzami w aplikacji Wiemy już, że interfejs użytkownika złożony jest z wielu formularzy oraz okien dialogowych. Do pokazywania lub chowania okien aplikacji można wykorzystać metody how i Hide. Zapamiętajmy, że wywołanie metody Hide powoduje jedynie ukrycie formularza, nie jest on jednak usuwany z pamięci. Dlatego też, jeśli formularz ten zostanie ponownie wyświetlony, będzie zawierał np. wszelkie dane jak mógł wprowadzić użytkownik, wartości zmiennych. Aby usunąć formularz zarówno z ekranu, jak i z pamięci komputera należy skorzystać z metody Close. W poprzednim artykule z tego cyklu Akademii PCkuriera przedstawione zostało słowo kluczowe Me, które pozwalało odwołać się z kodu do bieżącego formularza. Aby z poziomu kodu bieżącego formularza wywołać metodę innego formularza należy skorzystać z prezentowanej składni: NazwaFormularza.NazwaMetody Przykładowo, aby w kodzie obsługi zdarzenia Click formularza Form1 wywołać metodę how formularza Form2 należy użyć poniższego kodu: Private ub Form1_Click(ByVal sender As Object, ByVal e As ystem.eventargs) Handles MyBase.Click Form2.Close() End ub Uwaga: linie 1 i 2 powyższego kodu należy zapisać w jednym wierszu Zapamiętaj, że możesz użyć danej metody formularza, o ile wcześniej w kodzie została utworzona jego instancja. Kontrolki Prawie każde okno aplikacji zawiera wizualne komponenty, pozwalające na realizację określonych działań użytkownika. Przykładem takich obiektów może być etykietka (Label) służąca do wyłącznie do prezentacji czy pole tekstowe (TextBox), dzięki któremu użytkownik może wprowadzać danych tekstowe. Innym przykładem takiego obiektu wizualnego jest przycisk. Komponenty, które umieszcza się na formularzu, budując w ten sposób interfejs użytkownika nazywa się kontrolkami ( Controls). Przykłady innych kontrolek prezentuje tabela: Nazwa kontrolki Opis ComboBox Lista rozwijana pozwalająca użytkownikowi na wybór sugerowanych wartości. Dzięki temu, że lista dopuszczalnych wartości może nie być prezentowana w całości, a jedynie rozwijana na życzenie użytkownika, pozwala na zaoszczędzenie miejsca na formularzu. GroupBox Kontener lub pojemnik służący do grupowania kontrolek. Najczęściej stosuje
PictureBox RadioButton się w celu osiągnięcia określonej estetyki formularza (grupowanie kontrolek ze względu na ich funkcję w aplikacji) lub do grupowania pól wyboru. łuży do prezentacji danych graficznych. Pozwala na prezentację obrazów zapisanych w formatach: BMP, GIF, JPEG, czy też plików ikon zapisanych w plikach z rozszerzeniem ICO. Pozwala na wybór jednej spośród kilku wartości. Ponieważ każda z nich zajmuje miejsce na formularzu, zaleca się, aby lista dopuszczalnych wartości była krótka. Zazwyczaj na formularzu grupuje się je przy pomocy kontrolki GroupBox. Praca z kontrolkami Tworzenie interfejsu użytkownika jest jednym z etapów tworzenia aplikacji. Na etapie tym pracuje się głównie z trzema oknami: oknem projektowania formularza (Form Designer), oknem przybornika zawierającym kontrolki (Toolbox) oraz oknem własności (Properties). Kontrolki można umieścić na formularzu korzystając z jednej z metod: Dwukrotne kliknięcie ikony dowolnej kontrolki w oknie Toolbox spowoduje dodanie do formularza nowej instancji tej kontrolki. Kontrolka ta będzie miała domyślną wielkość i położenie. Po dodaniu każdej z kontrolek do formularza należy określić ich położenie oraz wielkość. Zaletą tej metody jest szybkość, z jaką można dodac wiele kontrolek. Kliknięcie ikony kontrolki w oknie Toolbox, a następnie określenie położenia i wielkości kontrolki poprzez zaznaczenie obszaru, jaki kontrolka powinna zajmować (należy trzymajć wciśnięty lewy przycisk myszy).druga z metod pozwala na dokładniejszą kontrolę położenia oraz wielkości kontrolki na formularzu Oczywiście, w każdej chwili można dokonać zmiany bieżącego położenia lub wielkości kontrolki. W celu zmiany położenia należykliknąć na kontrolce i trzymając wciśnięty lewy przycisk myszy przesunąć mysz, aby zmienić położenie kontrolki na formularzu Zmieniając wielkość należy przeciągnąć odpowiednio jeden z ośmiu uchwytów, jakie znajdziemy na krawędziach i rogach kontrolki. Własności kontrolek W celu zmiany własności kontrolek, podobnie jak w przypadku formularza, należy skorzystać z okna własności. Własności te określają zarówno cechy wizualne kontrolki ( wielkość, położenie czy prezentowane przez kontrolkę dane), jak i aspekty związane z funkcjonalnością kontrolki (np. znak maskujący czy też dopuszczalna liczba znaków).
Aby okno własności prezentowało własności danej kontrolki w trybie projektowania formularza należy uaktywnić ją korzystając z listy rozwijanej Objects w górnej części okna własności. Lista ta zawiera nazwę i klasę każdej z kontrolek umieszczonych na formularzu. Zwróćmy uwagę, że po kliknięciu na dowolnej własności kontrolki lub formularza w dolnej części okna własności w panelu Description, pojawia się jej skrótowy opis. Pracę z oknem własności (podobnie jak w przypadku formularza) znacznie ułatwiają ikony Categorized oraz Alphabetic, pozwalające na zmianę kolejności wyświetlanych własności (alfabetycznie lub wg kategorii znaczenia). Jeśli zachodzi taka potrzeba, można jednocześnie zmieniać wartość własności wielu kontrolek. Aby to zrobić, najpierw należy kliknąć na każdej kontrolce jednocześnie przytrzymując klawisz Ctrl. Po wykonaniu powyższej czynności lista Object w oknie własności nie będzie wyświetlała nazwy żadnej z kontrolek, a poniżej będą prezentowane wyłącznie te własności, którymi dysponuje każdy z wybranych obiektów. Metoda ta jest przydatna np. wówczas, gdy chcemy zmienić czcionkę, wykorzystywaną do prezentacji tekstu. Podczas dodawania do formularza nowej kontrolki Visual Basic.NET automatycznie nada jej domyślną nazwę, powstałą z połączenia nazwy klasy kontrolki oraz kolejnego numeru instancji. Nazwę kontrolki można,(a nawet należy zmienić (korzystając z własności Name) tak, aby lepiej określała rolę, jaką pełni na formularzu. Tabela prezentuje najczęściej używane własności niektórych z kontrolek. Typ kontrolki Nazwa własności Opis ComboBox Items Lista elementów wyświetlanych przez listę rozwijaną. GroupBox Text Tekst prezentowany w górnej części obramowania. PictureBox Image Plik graficzny prezentowany przez kontrolkę. RadioButton Checked Określa, czy po uruchomieniu aplikacji pole zostanie zaznaczone. Zdarzenia kontrolek Kontrolki podobnie jak formularze eksponują określone zdarzenia. Tworzenie procedury obsługi zdarzenia kontrolki i formularza jest podobne, różni się jedynie tym, że z listy ClassName należy wybrać nazwę danej kontrolki. Następny odcinek Akademii PCkuriera rozpoczniemy od opisu klasy MessageBox, pozwalającej na wyświetlanie prostych okien dialogowych. Nieco miejsca poświęcimy także prawidłowej stylizacji kodu oraz jego formatowaniu i komentowaniu.