menu

darmowe eBooki

Programuję w Delphi i C++ Builder

okładka

Jak szybko nauczyć się programowania w dwóch różnych językach?

Sprawdź sam, czytając darmowy fragment eBooka Programuję w Delphi i C++ Builder.

Czy ta wiedza okazała się dla Ciebie przydatna? Chcesz wiedzieć więcej? Zobacz tutaj.

Google Adsense

migawka z forum

Dowcipy o programistach/informatykach

Witam, grunt to potrafić śmiać sie z samego siebie  ;DPrzychodzi informatyk do domu po pra...

Rysiek z "Klanu"

W związku z ogromnym poruszeniem we wszystkich mediach w naszym kraju, dotyczącym tak kultowej postaci jak Rysiek z &quo...

Propozycje zmian w serwisie Guide C++

Witam, ze względu na to że nie znalazłem podobnego tematu na forum, a mam kilka sugestii   ;) postanowiłem je ...

buttony

SDJ
vortal programistów
Vademecum sieci komputerowych
Soldiers'04 - fan klub Legii Warszawa
www.katalog.bajery.pl
katalog stron
katalog najlepszych stron
jestem w katalogu
Wszystko o C++
[zamknij]

Korzystamy z plików cookies i umożliwiamy zamieszczanie ich osobom trzecim. Pliki cookie pozwalają na poznanie twoich preferencji na podstawie zachowań w serwisie.
Uznajemy, że jeżeli kontynuujesz korzystanie z serwisu, wyrażasz na to zgodę.

jesteś w: Kurs WinAPI / Procedura obsługi okna
Szkoła Hakerów - Kurs Hackingu Bez Cenzury

Procedura obsługi okna

W lekcjach poprzednich nadmieniłem conieco o procedurze obsługi okna i komunikatach. Teraz powiemy sobie nieco więcej na ten temat i poznamy zasadę działania aplikacji opartej na komunikatach. Dla formalności wyjaśnijmy sobie [a raczej przypomnijmy] czym jest komunikat. Otóż komunikat [message], to po prostu jakieś zdarzenie [event]. Zdarzeniem w Windows'ie jest dosłownie wszystko, co może wpłynąć na wygląd, bądź działanie aplikacji. Począwszy od kliknięcia myszą, wciśnięcia jakiegoś klawisza, otwarcia listy rozwijanej, na ustawieniu aktywnego fokusa na wskazanej kontrolce kończąc. Dla niewtajemniczonych powiem, że fokus, czy też ognisko to takie 'kropeczki' wokół aktywnej kontrolki. Komunikatów jest naprawdę sporo i nie sposób ich wszystkich tutaj przytoczyć. Najważniejsze jest zrozumienie samego mechanizmu działania procedury obsługi okna. Gdy już to pojmiesz to nie będziesz miał problemów z opanowaniem coraz to nowszych komunikatów. Zacznijmy od budowy procedury.

  1. LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3. //tutaj znajduje się obsługa komunikatów
  4. }

Jak widać funkcja przyjmuje cztery argumenty. Pierwszy to uchwyt kontrolki, która wysłała komunikat. Drugi to dowolna liczba większa od zera określająca treść owego komunikatu. Spis komunikatów znajdziesz w dokumentacji Dwa pozostałe są ściśle związane z samym komunikatem. Ich zawartość jest uzależniona od tego, jaki komunikat przywędrował do procedury. Może to być np. kod wciśniętego klawisza, koordynaty kursora bądź inne podobne informacje. Wiemy już trochę więcej. Pora teraz spożytkować tę wiedzę. Skorzystamy z przykładu z lekcji poprzedniej.

  1. #include <windows.h>
  2. //deklaracja zapowiadająca
  3. LRESULT CALLBACK NaszaProcedura (HWND hwnd, UINT message, WPARAM wpar, LPARAM lpar);
  4.  
  5. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpsCmdLine, int nMode)
  6. {
  7. HWND hOkno;
  8. MSG message;
  9. WNDCLASS okno;
  10.  
  11. okno.hInstance = hInstance;
  12. okno.lpszClassName = "klasa główna";
  13. okno.lpfnWndProc = NaszaProcedura; //tutaj pojawia się nowość!!
  14. okno.lpszMenuName = NULL;
  15. okno.style = 0;
  16. okno.hIcon = LoadIcon (NULL, IDI_WINLOGO);
  17. okno.hCursor = LoadCursor (NULL, IDC_ARROW);
  18. okno.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
  19. okno.cbClsExtra = 0;
  20. okno.cbWndExtra = 0;
  21. if(!RegisterClass (&okno)) return 0;
  22. hOkno = CreateWindow ("klasa główna", "łokno :p",
  23. WS_OVERLAPPEDWINDOW, 100,100,200,100,
  24. NULL, NULL, hInstance, NULL);
  25. ShowWindow (hOkno, SW_SHOW);
  26.  
  27. while (GetMessage (&message, NULL, 0, 0))
  28. {
  29. TranslateMessage (&message);
  30. DispatchMessage (&message);
  31. }
  32. }

Pierwszą rzeczą, która uległa zmianie w stosunku do poprzedniego programu jest umieszczenie deklaracji zapowiadającej naszej procedury tuż przed funkcją główną WinMain. Ta deklaracja jest po to, aby kompilator nie protestował w momencie napotkania tej linijki: okno.lpfnWndProc = NaszaProcedura; Dzięki deklaracji kompilator ma jasność i wie, że NaszaProcedura to jakaś tam funkcja. Nie wie wprawdzie gdzie ona się znajduje, ale w tej chwili nie jest to potrzebne. Deklaracja w zupełności wystarczy. Takie postępowanie ma sens, gdyż nie zaciemnia kodu programu. Skoro już podczepiliśmy naszą procedurę do klasy okna, musimy sobie ją w końcu napisać. No właśnie, tylko jak się do tego zabrać? Nie będzie tak trudno, bo wiemy już dość dużo. Zatrzymajmy się jednak na moment i zastanówmy, co tak naprawdę nasza procedura powinna robić? W celach edukacyjnych napiszemy procedurkę, która w momencie kliknięcia jednego z przycisków z paska systemowego [chodzi o te trzy przyciski w prawym, górnym rogu okna] wyświetli stosowną informację. Tylko jak sprawdzić, co zostało kliknięte i czy w ogóle kliknięcie nastąpiło? Tutaj z pomocą przychodzą nam komunikaty. W momencie kliknięcia na którymś z trzech wspomnianych przycisków do procedury zostaje wysłany komunikat WM_SYSCOMMAND. Oczywiście musimy jeszcze jakoś zorientować się, który przycisk wciśnięto. Na nasze szczęści ta informacja zawarta jest w zmiennej typu WPARAM, która u nas nazywa się wpar.

  1. //oto nasza procedura obsługi okna
  2. LRESULT CALLBACK NaszaProcedura (HWND hwnd, UINT message, WPARAM wpar, LPARAM lpar)
  3. {
  4. switch (message)
  5. {
  6. case WM_SYSCOMMAND:
  7. switch (wpar)
  8. {
  9. case SC_CLOSE:
  10. //wyświetlenie okienka z informacją i zakończenie programu
  11. MessageBox (hwnd, "koniec", "", MB_OK);
  12. PostQuitMessage (0);
  13. break;
  14.  
  15. case SC_MINIMIZE:
  16. MessageBox (hwnd, "minimalizacja", "", MB_OK);
  17. break;
  18.  
  19. case SC_MAXIMIZE:
  20. MessageBox (hwnd, "maksymalizacja", "", MB_OK);
  21. break;
  22. }
  23. default:
  24. return DefWindowProc (hwnd, message, wpar, lpar);
  25. }
  26. }

Teraz to dopiero będę musiał się tłumaczyć. Ale chyba nie mam wyjścia ;) W ciele procedury znajduje się instrukcja switch (message), w której rozpoznajemy rodzaj komunikatu. Jeżeli jest to komunikat WM_SYSCOMMAND oznacza to, że został kliknięty któryś z przycisków na pasku tytułowym. Trzeba teraz rozpoznać, który i odpowiednio zareagować. Tak więc znów pojawia się instrukcja switch (wpar), w której sprawdzamy, jaka jest wartość argumentu wpar. Jeżeli jest to wartość SC_CLOSE wyświetlamy odpowiednie okienko i kończymy program wywołując funkcję PostQuitMessage(0). Identycznie wygląda sprawa z minimalizacją i maksymalizacją. Należy tutaj jeszcze pamiętać o bardzo ważnej rzeczy. Mianowicie każdy nieobsłużony komunikat należy zwrócić do oryginalnej procedury okna! Dlatego też w pierwszym bloku switch (message) za etykietą default: pojawia się instrukcja return DefWindowProc(hwnd, message, wpar, lpar);. A teraz mała zagadka. Czy w momencie kliknięcia na przycisk minimalizacji lub maksymalizacji faktycznie okno zachowa się w należyty sposób? Zauważ, że nasza procedura wcale tego nie robi! Ona jedynie wyświetla stosowną informację. Spójrz raz jeszcze na fragment kodu:

  1. switch (message)
  2. {
  3. case WM_SYSCOMMAND:
  4. switch (wpar)
  5. {
  6. case SC_CLOSE:
  7. //wyświetlenie okienka z informacją i zakończenie programu
  8. MessageBox (hwnd, "koniec", "", MB_OK);
  9. PostQuitMessage (0);
  10.  
  11. //wyskok do bloku switch(message), [ale tylko teoretyczny]
  12. break;
  13.  
  14. case SC_MINIMIZE:
  15. //wyświetlenie okienka z informacją i wyskok do bloku switch(message)
  16. MessageBox (hwnd, "minimalizacja", "", MB_OK);
  17. break;
  18.  
  19. case SC_MAXIMIZE:
  20. //wyświetlenie okienka z informacją i wyskok do bloku switch(message)
  21. MessageBox (hwnd, "maksymalizacja", "", MB_OK);
  22. break;
  23. }
  24. break; //tego nam zabrakło
  25. default:
  26. return DefWindowProc (hwnd, message, wpar, lpar);
  27. }

Chyba już rozumiesz, jak to jest zrobione. Po prostu po rozpoznaniu przycisku następuje wyskok o jeden poziom wyżej, czyli zawsze trafiamy na instrukcję stojącą po etykiecie default. Tam znajduje się wywołanie standardowej procedury obsługi, która doskonale 'wie' jak zminimalizować, bądź zmaksymalizować okno. Wyjątkiem jest oczywiście pierwszy wariant, gdzie następuje zamknięcie programu.