Tworzenie graficznego interfejsu użytkownika (GUI) Programowanie Windows Tworzenie graficznego interfejsu użytkownika (GUI) Jacek Matulewski 15 marca 2015 http://www.fizyka.umk.pl/~jacek/dydaktyka/winprog/
Powtórzenie Rozwinięcie projektu „WinMain_InicjacjaOkna” Funkcja WinMain (wejście, ang. entry point) Klasa C++ okna Okno Procedura okna, funkcja WndProc i metoda klasy C++ Tworzenie okna (RegisterClassEx, CreateWindow) Kontrolki są oknami – otrzymują komunikaty
Tworzenie i obsługa kontrolek GUI Tworzenie kontrolki: CreateWindow Korzystamy z istniejących klas: klasa przycisku jest zarejestrowana pod nazwą „Button”, suwaka - „msctls_trackbar32” (alias TRACKBAR_CLASS) Aby kontrolka była „żywa”, okno musi reagować na komunikaty WM_COMMAND przysyłane po kliknięciu przycisku My określamy numer wParam identyfikujący przycisk
Tworzenie przycisków Funkcja składowa tworząca dwa przyciski: void COkno::TworzPrzyciski(HWND uchwytOknaRodzica) { hPrzyciskHello = CreateWindow( "Button", //nazwa klasy "Hello World!", //etykieta WS_CHILD | WS_VISIBLE, //styl 30, 30, 200, 70, //geometria uchwytOknaRodzica, (HMENU)ID_BUTTON_HELLO, //identyfikator (wParam) wc.hInstance, NULL);
Tworzenie przycisków Funkcja składowa tworząca dwa przyciski: void COkno::TworzPrzyciski(HWND uchwytOknaRodzica) { ... hPrzyciskZamknij = CreateWindow( "Button", "Zamknij", WS_CHILD | WS_VISIBLE, 240, 30, 200, 70, uchwytOknaRodzica, (HMENU)ID_BUTTON_ZAMKNIJ, wc.hInstance, NULL); } Uchwyt do „okna” przycisku
Obsługa przycisków Funkcja składowa dedykowana do obsługi przycisków: void COkno::ObslugaPrzyciskow(WPARAM wParam) { switch(wParam) case ID_BUTTON_HELLO: MessageBox(this->uchwytOkna,"Hello World!", "Witaj świecie!",MB_OK); break; case ID_BUTTON_ZAMKNIJ: PostMessage(this->uchwytOkna,WM_CLOSE,0,0); } Przekształcanie komunikatów (klawiatury)
Tworzenie i obsługa w WndProc Wywołanie obu metod w procedurze okna LRESULT COkno::WndProc(HWND hWnd, UINT message, WPARAM wParam,LPARAM lParam) { switch (message) case WM_CREATE: TworzPrzyciski(hWnd); break; case WM_COMMAND: ObslugaPrzyciskow(wParam); ...
Demo: Przyciski Kontynuacja aplikacji „WinMain_InicjacjaOkna” Czyste WinAPI (z pustego projektu)
Inne kontrolki Z innymi kontrolkami z GDI jest podobnie… Panel, który nie reaguje na działania użytkownika: hPanel = CreateWindow( "STATIC", "", //pusta etykieta WS_CHILD | WS_VISIBLE, margines, margines, szerokosc, wysokosc, hWnd, //uchwyt okna (HMENU)ID_PANEL, wc.hInstance, //GetModuleHandle(NULL), NULL);
Inne kontrolki Kontrolki z biblioteki Common Controls (plik comctl32.dll) Inicjacja biblioteki za pomocą funkcji InitCommonControlsEx, Struktura INITCOMMONCONTROLSEX pozwala określić, które zbiory bibliotek wczytać np. ICC_BAR_CLASSES Tworzenie standardowo za pomocą funkcji CreateWindow RECT rect; HWND hwndTrack = CreateWindow( TRACKBAR_CLASS, "Kontrolka Trackbar", WS_CHILD | WS_VISIBLE | TBS_ENABLESELRANGE | TBS_AUTOTICKS, rect.left, rect.top, ...
Inne kontrolki W czystym WinAPI nie mamy klas pozwalających na łatwe ustalanie własności kontrolek (por. MFC, VCL, QT); konfigurowanie kontrolek możliwe dzięki wysyłaniu do nich komunikatów (z pominięciem okna): SendMessage(hwndTrack, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG(min, max)); SendMessage(hwndTrack, TBM_SETPAGESIZE, 0, (LPARAM) 4); SendMessage(hwndTrack, TBM_SETTICFREQ, 15, (LPARAM) 1); SendMessage(hwndTrack, TBM_SETSEL, (WPARAM) FALSE, (LPARAM) MAKELONG(selMin, selMax)); SendMessage(hwndTrack, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) selMin); SetFocus(hwndTrack);
Inne kontrolki Procedura okna – przesuwanie suwaków, powoduje zmianę koloru panelu (pozycje suwaków = składowe RGB koloru) i odświeżenie panelu case WM_CTLCOLORSTATIC: { DWORD dwPos1 = SendMessage(hTrackBar1, TBM_GETPOS, 0, 0); DWORD dwPos2 = SendMessage(hTrackBar2, TBM_GETPOS, 0, 0); DWORD dwPos3 = SendMessage(hTrackBar3, TBM_GETPOS, 0, 0); HWND hCtl =(HWND)lParam; HBRUSH brush=CreateSolidBrush( RGB((int)dwPos1,(int)dwPos2,(int)dwPos3)); if(hCtl == hPanel) return (LRESULT) brush; else return (LRESULT)GetStockObject(WHITE_BRUSH); } case WM_HSCROLL: RedrawWindow(hPanel,NULL,NULL,RDW_INVALIDATE); break;
Demo: Kolory Kontynuacja aplikacji „Przyciski” Czyste WinAPI (z pustego projektu) Adaptacja rozmiaru kontrolek przy zmianie rozmiaru okna
Odczyt i zmiana „własności” okien MSDN „Develop desktop apps”: https://msdn.microsoft.com/pl-pl/library/windows/desktop/ Lista funkcji dotyczących okien i kontrolek : https://msdn.microsoft.com/pl-pl/library/windows/desktop/ms632595(v=vs.85).aspx Pierwszym argumentem tych funkcji jest zawsze uchwyt okna Tytuł okna: SetWindowText, GetWindowTest, Równoważne wysłanie komunikatu: WM_SETTEXT Położenie: SetWindowPlacement, SetWindowPos, Są również analogiczne funkcje Get.. Funkcja: MoveWindow, ShowWindow SetActiveWindow, SetForegroundWindowRect BringWindowToTop, funkcje Get.. oraz GetTopWindow
Odczyt i zmiana „własności” okien Kontrolki i okna-dzieci: SetParent, GetParent Informacje o oknie: GetWindowInfo Położenie inaczej: GetWindowRect, GetClientRect (por. GetWindowPos i GetWindowPlacement), Struktura RECT (left, top, right, bottom) AdjustWindowRect(Ex) – oblicza zewnętrzny rozmiar okna na podstawie podanego rozmiaru obszaru klienta Zamykanie: CloseWindow, DestroyWindow Pierwsza wysyła komunikat WM_CLOSE, w którym można wyświetlić pytanie. Jeżeli jest zgoda na zamknięcie, należy wywołać drugą funkcję, która rzeczywiście zamyka okno AnimateWindow – animacje tworzenia i zamykania okna
Demo: Lista okien (MFC) Funkcje: EnumWindows, EnumChildWindows Callback: EnumWindowProc
Ciekawostka: zmiana kształtu okna Regiony, region dostępny poprzez uchwyt HRGN Tworzenie regionów: CreateRectRgn, CreateRoundRectRgn, CreateEllipticRgn, CreatePolygonRgn, CombineRgn Wypełnianie regionu: FillRgn (argumentem jest pędzel) Ustalanie kształtu okna na bazie regionów: SetWindowRgn, GetWindowRgn Inne zastosowanie: detekcja ruchu i kliknięć myszy
Przykładowe pytania Jakiej funkcji należy użyć do utworzenia okna, a jakiej do utworzenia „kontrolki”? Czym jest klasa okna? Jakie zawiera informacje? Jaka funkcja służy do znalezienia uchwytu okna o znanej nazwie klasy? Do czego służy procedura okna? Jak wykonać pętlę po wszystkich oknach i ich oknach-dzieciach? Do czego służy funkcja AdjustWindowRect? Czy można zmienić tytuł okna z innej aplikacji? Jakiej użyć do tego funkcji? A jakiej w przypadku „własnego” okna?