Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

GUI - Úvod •Něco málo teorie –Aplikace řízené tokem událostí (Event driven applications) –MVC – Model View Controller •Win 32 API –Okna a zprávy.

Podobné prezentace


Prezentace na téma: "GUI - Úvod •Něco málo teorie –Aplikace řízené tokem událostí (Event driven applications) –MVC – Model View Controller •Win 32 API –Okna a zprávy."— Transkript prezentace:

1 GUI - Úvod •Něco málo teorie –Aplikace řízené tokem událostí (Event driven applications) –MVC – Model View Controller •Win 32 API –Okna a zprávy

2 Aplikace řízené událostmi Event driven applications •Také Event driven programming –Používá se např. v OS (přerušení) –GUI Fronta zpráv Zpráva Výběr zprávy Odeslání zprávy (dispatch) Smyčka zpráv Zpracování zprávy Nové zprávy

3 MVC Model View Controller • Trygve Mikkjel – SmallTalk (Xerox) •SW architektura, která odděluje –Model = Datový model –View = Interface a zobrazení (např. GUI) –Controller = Řídící logika, reakce na události •Použit např. v –MFC –Od QT od release 4 –NeXTStep –Java SWING (?) –Windows Presentation Foundation (WPF) •Podobné MVC •.Net 3.0 (původně WinFX), nativně na Vistách

4 MVC •Plné čáry – přímé spojení •Čárkované čáry – nepřímé spojení Jak to funguje •Vstup od uživatele (např. zmáčknutí tlačítka v GUI) •Controller zpracuje uživatelský vstup (handler nebo callback) –zaktualizuje model dle vstupu •View upraví dle modelu svůj vzhled (GUI) –Model by neměl mít přímé povědomí o View (View si získává data od modelu) •Ale může si zaregistrovat akce pro změny položek modelu (Observer, Listener) –Controller nepředává Model přímo View

5 Win 32 API GUI – okna, zprávy

6 Okna Literatura a turoriály •Stránky Microsoftu – MSDN •Knihy o Win 32 API •http://www.stromcode.com/modules.php?n ame=Glowdot_Tutorials&page=1&tid=1&o p=viewhttp://www.stromcode.com/modules.php?n ame=Glowdot_Tutorials&page=1&tid=1&o p=view •http://www.winprog.org/tutorial/http://www.winprog.org/tutorial/ •Google :-)

7 Okna •Všechno je okno –Včetně olvádacích prvků •controls (prvky GUI) - widgety •Prvky GUI mají svůj handle –většina GUI funkcí používá handle –V C definovány typy pro různé handle •Začínají na H – HICON, HBRUSH.... •Také okno je určeno svým handlem –HWND

8 Okna •Vytvoření okenní aplikace –Hlavní okno •Registrace třídy okna •Vytvoření okna •Zobrazení okna •Zpracování zpráv –Smyčka událostí •Vybíraní zprávy •Dispatching

9 Okno části okna •Každé okna má určité části •Zobrazení daných částí je řízeno –styly okna –typem okna

10 Registrace třídy okna •Třída okna (myšleno jako druh okna) –Nemá přímou souvislost s OOP –Nezaměňovat s třídami v C++ nebo v C# •Struktura WNDCLASS nebo WNDCLASSEX •Zavolání RegisterClass nebo RegisterClassEx

11 Registrace třídy okna •ATOM RegisterClassEx(CONST WNDCLASSEX *lpwcx ); •Vrací ATOM •Všimněte si nastavení velikosti struktury •Definice procedury okna WNDCLASSEX WndClsEx; WndClsEx.cbSize = sizeof(WNDCLASSEX); WndClsEx.style = CS_HREDRAW | CS_VREDRAW; WndClsEx.lpfnWndProc = WndProcedure; WndClsEx.cbClsExtra = 0; WndClsEx.cbWndExtra = 0; WndClsEx.hIcon = LoadIcon(NULL, IDI_APPLICATION); WndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW); WndClsEx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); WndClsEx.lpszMenuName = NULL; WndClsEx.lpszClassName = "MojeTestovaciOkno"; WndClsEx.hInstance = hInstance; WndClsEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&WndClsEx)

12 Vytvoření okna •Vytvoří okno a vrátí handle na něj nebo NULL •lpClassName může být jméno okna nebo atom třídy •Dostupné třídy oken poskytované přímo Windows –COMBOBOX –EDIT –LISTBOX –MDICLIENT –RichEdit –RICHEDIT_CLASS –SCROLLBAR –STATIC HWND CreateWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam );

13 Zničení okna •Okno se zruší pomocí BOOL DestroyWindow( HWND hWnd // handle to window to destroy ); –Zruší okno –Zruší menu –Zruší timery –Vyprázdní frontu zpráv pro dané okno –Zruší také okna, které jsou vlastněné daným oknem a také child okna

14 Zobrazení okna •Vytvořené okno zobrazíme BOOL ShowWindow( HWND hWnd, // handle to window int nCmdShow // show state ); nCmdShow – SW_HIDE, SW_SHOW, SW_MAXIMIZE, SW_MINIMIZE, … Pokud se nastaví WS_VISIBLE při volání CreateWindow, tak se okno automaticky zobrazí •Vytvořené okno necháme vykreslit BOOL UpdateWindow( HWND hWnd // handle to window ); • Překreslí client area (pošle zprávu)

15 Smyčka událostí •Windows doručují zprávy do fronty událostí •Windows nevolají přímo call back funkce •Aplikace si musí zprávy sama vyzvednout –Je možné filtrovat zprávy –Zprávy je pak možné předat daným call back funkcím

16 Smyčka událostí •Zpráva je –Definována pomocí ID •integer •Definovány v include souborech (WinUser.h) –Má navíc parametry • wParam typu WPARAM (32-bitový integer na Win32) • lParam typu LPARAM (32-bitový integer na Win32) –Parametry jsou specifické pro danou zprávu a můžou mít různý význam –Lze si nadefinovat i vlastní zprávy

17 Smyčka událostí Smyčka událostí (zpráv) obecně Fronta zpráv Zpráva Výběr zprávy Odeslání zprávy (dispatch) Smyčka zpráv Zpracování zprávy Nové zprávy

18 Smyčka událostí •Ve Windows se smyčka událostí realizuje takto: BOOL code; while((code=GetMessage(&msg,NULL,0,0))!= 0) { if (code==-1) { // nastala chyba } else { TranslateMessage(&msg); DispatchMessage(&msg); }

19 Smyčka událostí BOOL GetMessage( LPMSG lpMsg, // message information HWND hWnd, // handle to window UINT wMsgFilterMin, // first message UINT wMsgFilterMax // last message ); •Pokud žádné zprávy nejsou, tak čéká (blokuje) •Do proměnné lpMsg uloží zprávu určenou pro okno hWnd • hWwnd – handle okna –NULL – zprávy pro jakékoliv okno nebo daný thread • wMsgFilterMin a wMsgFilterMax –Přijme jenom zprávy, jejichž ID jsou v daném rozsahu

20 Smyčka událostí •Formát zprávy je následující typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG; • pt – souřadnice kurzoru myši v obrazovkových souřadnicích v době, kdy zpráva byla poslána • time – čas v okamžiku poslání zprávy

21 Smyčka událostí BOOL GetMessage( LPMSG lpMsg, // message information HWND hWnd, // handle to window UINT wMsgFilterMin, // first message UINT wMsgFilterMax // last message ); •Návratová hodnota je BOOL, ale –Vrátí 0: byla poslána zpráva WM_QUIT –Vráti -1: nastala chyba (dá se zjistit pomocí GetLastError ) –Vrátí cokoli jiného: přišla zpráva

22 Smyčka událostí BOOL PeekMessage( LPMSG lpMsg, // message information HWND hWnd, // handle to window UINT wMsgFilterMin, // first message UINT wMsgFilterMax, // last message UINT wRemoveMsg // removal options ); •Funkce podobná GetMesage, ale pokud nejsou žádné zprávy, tak se hned vrátí •Vrátí 0 pokud nejsou žádné zprávy •Poslední parametr určuje, zda-li se má zpráva z fronty odstranit ( GetMesage vždy zprávu odstraní)

23 Smyčka událostí BOOL TranslateMessage( CONST MSG *lpMsg // message information ); •Přeloží zprávu - virtual-keys -> char – WM_KEYDOWN, WM_KEYUP přeloží na WM_CHAR nebo WM_DEADCHAR – WM_SYSKEYDOWN, WM_SYSKEYUP přeloží na WM_SYSCHAR nebo WM_SYSDEADCHAR •Nemodifikuje danou zprávu – pošle novou zprávu •Vrátí 0, pokud zpráva není přeložena •Vrátí nenulovou hodnotu, pokud byla zpráva přeložena

24 Smyčka událostí LRESULT DispatchMessage( CONST MSG *lpmsg // message information ); •Doručí zprávu proceduře daného okna •Návratová hodnota je dána návratovou hodnotou okenní procedury –Většinou se ignoruje •Pokud je zpráva typu WM_TIMER a lParam není NULL – lParam obsahuje adresu funkce, která se zavolá místo procedury okna

25 Smyčka událostí Pořadí zpráv, jak se doručují •Sent messages •Posted messages •Input (hardware) messages and system internal events •Sent messages (again) • WM_PAINT messages • WM_TIMER messages

26 Poslání zprávy BOOL PostMessage( HWND hWnd, // handle to destination window UINT Msg, // message WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ); •Pošle zprávu danému oknu •Zpráva se uloží do smyčky zpráv •Nečeká se na výsledek, program pokračuje hned dále •Vrátí nulu, pokud volání selže

27 Poslání zprávy LRESULT SendMessage( HWND hWnd, // handle to destination window UINT Msg, // message WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ); •Pošle zprávu danému oknu •Zavolá proceduru okna - nejde přes smyčku zpráv –Pokud je okno ze stejného threadu zavolá proceduru přímo (jako podprogram) –Pokud ne, tak je ji potřeba zpracovat v druhém threadu – uloží se do fronty zpráv •Čeká se, dokud zpráva není zpracována

28 Procedura okna typedef struct _WNDCLASSEX { UINT cbSize; UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; HICON hIconSm; } WNDCLASSEX, *PWNDCLASSEX; •Zadává se při registraci třídy okna pomocí RegisterClassEx –Položka: WNDPROC lpfnWndProc

29 Procedura okna LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); •Obsluhuje zprávy poslané danému oknu •Většinou implementováno jako velký switch •Pokud procedura okna danou zprávu neobslouží, tak by se měl zavolat standardní handler – return DefWindowProc(hwnd, uMsg, wParam, lParam);

30 #include LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE:{ DestroyWindow(hwnd); return 0; } case WM_DESTROY:{ PostQuitMessage(0); return 0; } } return DefWindowProc(hwnd, msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX);wc.style = 0; wc.lpfnWndProc = WndProc;wc.cbClsExtra = 0; wc.cbWndExtra = 0;wc.hInstance = hInstance; wc.lpszMenuName = NULL;wc.lpszClassName = "X36APIClass"; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) COLOR_APPWORKSPACE; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) return -1; HWND hwnd=CreateWindowEx(WS_EX_CLIENTEDGE,"X36APIClass","API",WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,256, 128,NULL, NULL, hInstance, NULL); if(hwnd==NULL) return -1; ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); BOOLcode; MSGmsg; while((code=GetMessage(&msg,NULL,0,0))!= 0) { if (code==-1) return -1; TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; }

31 #include HWNDbutton; LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE:{ DestroyWindow(hwnd); return 0; } case WM_DESTROY:{ PostQuitMessage(0); return 0; } case WM_COMMAND: { if((HWND) lParam==button) MessageBox(NULL,"Clicked!","Hey",MB_OK); return 0; } return DefWindowProc(hwnd, msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX);wc.style = 0; wc.lpfnWndProc = WndProc;wc.cbClsExtra = 0; wc.cbWndExtra = 0;wc.hInstance = hInstance; wc.lpszMenuName = NULL;wc.lpszClassName = "X36APIClass"; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) COLOR_APPWORKSPACE; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) return -1; HWND hwnd=CreateWindowEx(WS_EX_CLIENTEDGE,"X36APIClass","API",WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,256, 128,NULL, NULL, hInstance, NULL); button=CreateWindow("BUTTON","Click!",WS_CHILDWINDOW | WS_VISIBLE | BS_PUSHBUTTON, 10,10,100,25,hwnd, NULL, hInstance, NULL); SetParent(button,hwnd); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); BOOLcode; MSGmsg; while((code=GetMessage(&msg,NULL,0,0))!= 0) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; }

32 Dialogy •Součástí aplikace můžou být resources –Lze je definovat v MSVC –Různé typy dat –V programu lze s nimi pracovat

33 Dialogy •Součástí resource jsou i šablony dialogů –Lze si „naklikat“ dialog v MSVC –Ošetření zpráv se, ale musí udělat ručně (nemluvíme zde o MSFC)

34 Dialogy HWND CreateDialog( HINSTANCE hInstance, // handle to module LPCTSTR lpTemplate, // dialog box template name HWND hWndParent, // handle to owner window DLGPROC lpDialogFunc // dialog box procedure ); •Každý dialog má okenní proceduru –Má jiný tvar než „normální“ procedura okna – BOOL CALLBACK DialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) •Vrací TRUE pokud byla zpráva zpracována, jinak FALSE •Nesmí se volat DefWindowProc

35 Dialogy •Pokud používáte dialog z resources –#include "resource.h" –V include souboru jsou konstanty pomocí kterých lze data z reousrces dostat –Makro – MAKEINTRESOURCE(IDD_DIALOG1) • IDD_DIALOG1 = id dialogu CreateDialog(hInstance,MAKEINTRESOURCE( IDD_DIALOG1),NULL,DialogProc);

36 Dialogy •Aby se správně zpracovávaly klávesové zkratky, je potřeba modifikovat hlavní smyčku událostí while((code=GetMessage(&msg,NULL,0,0))!= 0) { if (code==-1) return -1; if(!IsDialogMessage(dialog, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); }

37 Dialogy - příklad •Následující kód vytvoří tento dialog pos stisknutí tlačítka

38 //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by GUI_HelloWorld1.rc // #define IDD_DIALOG1 101 #define IDC_EDIT // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE #define _APS_NEXT_CONTROL_VALUE 1005 #define _APS_NEXT_SYMED_VALUE 101 #endif Dialogy - příklad •Automaticky vygenerovaný soubor resource1.h

39 //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by GUI_HelloWorld1.rc // #define IDD_DIALOG1 101 #define IDC_EDIT // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE #define _APS_NEXT_CONTROL_VALUE 1005 #define _APS_NEXT_SYMED_VALUE 101 #endif Dialogy - příklad •Automaticky vygenerovaný soubor resource1.h •Resource soubor (.rc) je textový soubor, který popisuje dané resources

40 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int show) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX);wc.style = 0; wc.lpfnWndProc = WndProc;wc.cbClsExtra = 0; wc.cbWndExtra = 0;wc.hInstance = hInstance; wc.lpszMenuName = NULL;wc.lpszClassName = "X36APIClass"; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) COLOR_APPWORKSPACE; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) return -1; HWND hwnd=CreateWindowEx(WS_EX_CLIENTEDGE,"X36APIClass","API",WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 256, 128,NULL, NULL, hInstance, NULL); button=CreateWindow("BUTTON","Click!",WS_CHILDWINDOW | WS_VISIBLE | BS_PUSHBUTTON, 10,10,100,25,hwnd, NULL, hInstance, NULL); dialog=CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DialogProc); SetParent(button,hwnd); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); BOOLcode; MSGmsg; while((code=GetMessage(&msg,NULL,0,0))!= 0) { if(code==-1) return -1; if(!IsDialogMessage(dialog, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; }

41 #include #include "resource1.h" HWNDbutton; HWNDdialog=NULL; LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE:{ DestroyWindow(hwnd); return 0; } case WM_DESTROY:{ PostQuitMessage(0); return 0; } case WM_COMMAND: { if((HWND) lParam==button) { ShowWindow(dialog,SW_SHOW); } return 0; } return DefWindowProc(hwnd, msg, wParam, lParam); } BOOL CALLBACK DialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) { if(uMsg==WM_COMMAND && ((LOWORD(wParam))==IDOK || (LOWORD(wParam))==IDCANCEL)) { ShowWindow(hwndDlg,SW_HIDE); return TRUE; } return FALSE; }


Stáhnout ppt "GUI - Úvod •Něco málo teorie –Aplikace řízené tokem událostí (Event driven applications) –MVC – Model View Controller •Win 32 API –Okna a zprávy."

Podobné prezentace


Reklamy Google