Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
OpublikowałRobert Ciesielski Został zmieniony 9 lat temu
1
Komunikaty Windows Jacek Matulewski 22 września 2012 Programowanie Windows http://www.fizyka.umk.pl/~jacek/dydaktyka/winprog/
2
Komunikaty Windows Komunikaty Windows (ang. Windows messages) to mechanizm przekazywania informacji od systemu do aplikacji (ew. między aplikacjami) – układ nerwowy Windows Przykładowe komunikaty: WM_LBUTTONDOWN, WM_LBUTTONUP WM_MOUSEMOVE, WM_NCMOUSEMOVE, WM_KEYDOWN, WM_KEYUP, WM_KEYCHAR, WM_DROPFILES, WM_CLOSE, WM_PAINT WM_DISPLAYCHANGE, WM_DEVICECHANGE WM_QUERYENDSESSION, WM_ENDSESSION, WM_SYSCOMMAND, WM_USER http://www.autohotkey.com/docs/misc/SendMessageList.htm
3
Pętla główna Każda aplikacja Windows musi mieć funkcję zwrotną (ang. callback) o nazwie WinMain. W niej umieszcza się pętlę główną aplikacji, której zasadniczym zadaniem jest odbieranie komunikatów z kolejki komunikatów aplikacji. WPARAM Run() { MSG msg; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
4
Pętla główna Każda aplikacja Windows musi mieć funkcję zwrotną (ang. callback) o nazwie WinMain. W niej umieszcza się pętlę główną aplikacji, której zasadniczym zadaniem jest odbieranie komunikatów z kolejki komunikatów aplikacji. WPARAM Run() { MSG msg; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } Zwraca 0 tylko dla WM_QUIT ; alt. PeekMessage typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG, *LPMSG; Przekształcanie komunikatów (klawiatury) Rozsyłanie komunikatów do okien-adresatów (w tym kontrolek)
5
Obsługa komunikatu Etap 1: Działanie użytkownika lub sytuacja w systemie System tworzy strukturę komunikatu MSG z numerem WM_ Wysyła komunikat do adresata (okno aplikacji lub jego dziecko) Etap 2: Struktura zostaje umieszczona w kolejce komunikatów aplikacji Istnieje jednak możliwość pominięcia kolejki i przesłania bezpośrednio do okna-adresata (kontrolki). Komunikat może być też rozsyłany do wszystkich okien (ang. broadcast) Etap 3: Aplikacja odbiera komunikat z kolejki i przesyła do właściwego pod-okna – a właściwie do tzw. procedury okna WndProc.
6
Procedura okna to funkcja zwrotna wskazywana w momencie rejestracji klasy okna, która jest wywoływana w momencie otrzymania przez okno komunikatu. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_SIZE: { int width = LOWORD(lParam); int height = HIWORD(lParam); OnSize(hwnd, (UINT)wParam, width, height); } break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } Procedura okna
7
Procedura okna to funkcja zwrotna wskazywana w momencie rejestracji klasy okna, która jest wywoływana w momencie otrzymania przez okno komunikatu. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_SIZE: { int width = LOWORD(lParam); int height = HIWORD(lParam); OnSize(hwnd, (UINT)wParam, width, height); } break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } Procedura okna W kodzie C++ okno zazwyczaj reprezentowane jest przez klasę ze zdefiniowaną metodą WndProc : LRESULT CALLBACK WndProc(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam) { return okno.WndProc(hWnd,message,wParam,lParam); } Filtrowanie komunikatów LOWORD i HIWORD – makra: #define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16)) #define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xFFFF)) OnSize to zdefiniowana przez nas funkcja dedykowana do obsługi komunikatu WM_SIZE Funkcja DefWindowProc wywołuje domyślną procedurę okna obsługującą wszystkie te komunikaty, które nas nie interesują (bez tego zamiast okna pojawia się tylko biała plama!). „Def” od default, a nie od definition. hwnd – uchwyt okna, czyli jednoznaczny identyfikator w danej sesji systemu
8
Funkcja PreTranslateMessage (MFC) Funkcja WindowProc uruchamiana jest dla ostatecznego okna- adresata (po rozdzieleniu w pętli obsługi komunikatów). Jeżeli kontrolka (np. ListBox ) przesłania część okna, to funkcja ta nie będzie „widzieć” komunikatów o ruchu myszy, gdy mysz jest nad kontrolką! Do odczytu wszystkich komunikatów, jeszcze przed rozesłaniem ich do poszczególnych kontrolek/okien służy metoda CWnd::PreTranslateMessage wywoływana przed TranslateMessage w pętli głównej okna MFC. BOOL CKomunikatyDlg::PreTranslateMessage(MSG* pMsg) { if(pMsg->message == WM_KEYDOWN) Beep(100,10); return CDialogEx::PreTranslateMessage(pMsg); }
9
Tworzenie okna (przy okazji) Struktury WNDCLASS ( EX ) –styl okna np. CS_HREDRAW | CS_VREDRAW | CS_OWNDC –procedura okna, –uchwyt bieżącej instancji aplikacji –ikony, kursor, pędzel tła np. (HBRUSH)(COLOR_WINDOW+1) –tytuł okna i nazwa klasy okna; oba łańcuchy umożliwiają wyszukiwanie okna funkcją FindWindow Rejestracja klasy okna: RegisterClass ( Ex ) Tworzenie okna: CreateWindow Pokazywanie, ukrywanie, maksymalizacja, minimalizacja okna: ShowWindow ( SW_SHOW, SW_HIDE,...) Aktualizacja okna: UpdateWindow
10
Demo: WinMain Klasa C++ „opakowująca” tworzenie i utrzymywanie okna Procedura ok na WndProc jako metoda (problem dostępu do składowych klasy C++ okna)
11
Demo: Komunikaty (MFC) Aplikacja MFC wyświetlająca komunikaty odbierane z kolejki komunikatów w liście ListBox. Co się stanie, gdy „odetniemy” komunikaty (zablokujemy ich obsługę przez aplikację usuwając wywołanie funkcji DefWindowProc )?
12
Mapowanie komunikatów (MFC) W MFC metody można związać z komunikatami za pomocą mechanizmu mapowania komunikatów (domyślny sposób obsługi komunikatów przeznaczonych dla kontrolek w VS): BEGIN_MESSAGE_MAP(CKomDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON1, &CKomDlg::OnBnClickedButton1) ON_BN_CLICKED(IDC_BUTTON2, &CKomDlg::OnBnClickedButton2) ON_BN_CLICKED(IDC_RADIO1, &CKomDlg::OnBnClickedRadio1) ON_BN_CLICKED(IDC_RADIO2, &CKomDlg::OnBnClickedRadio1) ON_BN_CLICKED(IDC_RADIO3, &CKomDlg::OnBnClickedRadio1) END_MESSAGE_MAP() W pliku nagłówkowym: DECLARE_MESSAGE_MAP()
13
Odczytywanie danych z kom. Komunikaty zwykle przekazują dodatkowe informacje o zdarzeniu (parametry lParam i wParam ). Przykład zdarzeń związanych z myszką: wchar_t txt_x[256]; wchar_t txt_y[256]; _itow_s(LOWORD(lParam),txt_x,256,10); _itow_s(HIWORD(lParam),txt_y,256,10); edit1.SetWindowText(txt_x); edit2.SetWindowText(txt_y);
14
Odczytywanie danych z kom. Komunikaty zwykle przekazują dodatkowe informacje o zdarzeniu (parametry lParam i wParam ). Odczytanie klawiatury: BOOL CKomunikatyDlg::PreTranslateMessage(MSG* pMsg) { //tu nie bedzie WM_CHAR if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) { Beep(300,200); }...
15
Wysyłanie komunikatów Uwaga! Standardowe funkcje WinAPI mają opakowania w klasie CWnd (MFC), które często „przesłaniają” zasadnicze funkcje. Wysyłanie komunikatów: PostMessage vs SendMessage. Pierwsza wysyła komunikat tradycyjnie tj. do kolejki komunikatów okna/kontrolki, druga – pomija kolejkę i wysyła bezpośrednio do okna/kontrolki. this->PostMessage(WM_CLOSE); //metoda klasy CWnd ::PostMessage( //funkcja czystego WinAPI this->m_hWnd, //uchwyt okna-adresata WM_CLOSE, //identyfikator komunikatu 0,0); //lParam i wParam
16
Wysyłanie komunikatów Uwaga! Standardowe funkcje WinAPI mają opakowania w klasie CWnd (MFC), które często „przesłaniają” zasadnicze funkcje. Wysyłanie komunikatów: PostMessage vs SendMessage. Pierwsza wysyła komunikat tradycyjnie tj. do kolejki komunikatów okna/kontrolki, druga – pomija kolejkę i wysyła bezpośrednio do okna/kontrolki. this->SendMessage(WM_SYSCOMMAND,SC_SCREENSAVE,0); ::SendMessage( this->m_hWnd, WM_SYSCOMMAND, SC_SCREENSAVE,0); Niektóre aplikacje pozwalają na ich kontrolowanie za pomocą komunikatów (np. WinAmp i Adobe).
17
Znajdywanie uchwytu okna Uchwyty okien (w tym kontrolek) można szukać korzystając z funkcji FindWindow podając tytuł okna lub nazwę jego klasy (zob. też FindWindowEx ): ::PostMessage( ::FindWindow(NULL,L"Komunikaty"), WM_CLOSE, 0,0); Przeszukiwanie okien w poszukiwaniu tych o konkretnych własnościach: EnumWindow i EnumChildWindows WindowFromPoint, ChildWindowFromPoint GetDesktopWindow, GetForegroundWindow, GetNextWindow, IsWindow, IsWindowVisible
18
Haki Można napisać bibliotekę DLL, która będzie ładowana do przestrzeni adresowej aplikacji w momencie np. wystąpienia zdarzenia związanego z klawiaturą lub myszą (po zarejestrowaniu tzw. haka – ang. hook). W takiej sytuacji nastąpi wywołanie funkcji zdefiniowanej w bibliotece DLL (potencjalnie niebezpieczne! - podsłuch). Uwaga! Przykład haka omówiony będzie na ćwiczeniach po tym, jak nauczymy się tworzyć biblioteki DLL z eksportowanymi funkcjami.
19
Przykładowe pytania Jakich funkcji WinAPI można użyć do wysłania komunikatu? Jaki komunikat służy do ukrycia/zamknięcia okna? Jaka funkcja służy do pobrania komunikatu z kolejki komunikatów? A jaka do jego pobrania bez usunięcia z kolejki? Jaka funkcja służy do znalezienia uchwytu okna o znanej nazwie klasy? Jak wykonać pętlę po wszystkich oknach i ich oknach- dzieciach? Opisz w jaki sposób haki mogą być zagrożeniem dla bezpieczeństwa użytkownika. „Naszkicuj” kod funkcji zwracającej uchwyt okna znajdującego pod kursorem myszy. Opcjonalnie zrób go oknem aktywnym.
20
Dodatek: Opis błędów Pobieranie opisu błędów dla wskazanego kodu błędu: FormatMessage Wyświetlanie: MessageBox (najpopularniejsza funkcja WinAPI) Demo: FormatMessage (MFC)
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.