Tworzenie graficznego
interfejsu użytkownika (GUI)
Jacek Matulewski
15 marca 2015 Programowanie Windows
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);
break;
} }
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);
break;
...
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?