Komunikaty Windows

Download Report

Transcript Komunikaty Windows

Programowanie Windows

Komunikaty Windows Jacek Matulewski

22 września 2012 http://www.fizyka.umk.pl/~jacek/dydaktyka/winprog/

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

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; }

{ HWND hwnd;

callback

) o nazwie komunikatów z

Pętla główna

• Każda aplikacja Windows musi mieć funkcję zwrotną (ang.

WinMain

. W niej umieszcza się pętlę główną aplikacji, której zasadniczym zadaniem jest odbieranie

kolejki komunikatów aplikacji

.

WPARAM Run() {

MSG

msg; while( Zwraca 0 tylko dla WM_QUIT ; alt. PeekMessage

GetMessage

Przekształcanie komunikatów (klawiatury) (&msg, NULL, 0, 0)) {

TranslateMessage

(&msg);

DispatchMessage

(&msg); } return msg.wParam; } Rozsyłanie komunikatów do okien-adresatów (w tym kontrolek)

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 .

Procedura okna

• 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; }

W kodzie C++ okno zazwyczaj reprezentowane jest przez klasę ze zdefiniowaną metodą WndProc :

Procedura okna

LRESULT CALLBACK WndProc(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam) { } • Procedura okna to funkcja zwrotna wskazywana w momencie rejestracji klasy okna, która jest wywoływana w momencie Filtrowanie komunikatów WPARAM wParam, LPARAM lParam) { OnSize switch (uMsg) { LOWORD i HIWORD – makra: #define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16)) #define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xFFFF)) } int height = HIWORD(lParam); OnSize(hwnd, (UINT)wParam, width, height); break; 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

.

}

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 gdy mysz jest nad kontrolką!

) przesłania część okna, to funkcja ta nie będzie „widzieć” komunikatów o ruchu myszy, • Do odczytu wszystkich komunikatów, jeszcze przed rozesłaniem ich do poszczególnych kontrolek/okien służy metoda przed CWnd::PreTranslateMessage TranslateMessage wywoływana w pętli głównej okna MFC.

BOOL CKomunikatyDlg::PreTranslateMessage(MSG* pMsg) { if(pMsg->message == WM_KEYDOWN) Beep(100,10); return CDialogEx::PreTranslateMessage(pMsg); }

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

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)

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 )?

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()

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);

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); } ...

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

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).

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

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.

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.

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)