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.