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

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

GUI - Úvod Něco málo teorie Win 32 API

Podobné prezentace


Prezentace na téma: "GUI - Úvod Něco málo teorie Win 32 API"— Transkript prezentace:

1 GUI - Úvod Něco málo teorie Win 32 API
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é

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 Jak to funguje Vstup od uživatele (např. zmáčknutí tlačítka v GUI)
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 ame=Glowdot_Tutorials&page=1&tid=1&o p=view Google :-)

7 Okna Všechno je okno Prvky GUI mají svůj handle
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 Zpracování zpráv 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 Vrací ATOM
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) ATOM RegisterClassEx(CONST WNDCLASSEX *lpwcx ); Vrací ATOM Všimněte si nastavení velikosti struktury Definice procedury okna

12 Vytvoření okna Dostupné třídy oken poskytované přímo Windows COMBOBOX
HWND CreateWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam ); 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

13 Zničení okna Okno se zruší pomocí Zruší okno Zruší menu Zruší timery
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 Má navíc parametry
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 Nové
Zpráva Výběr zprávy Odeslání zprávy (dispatch) Smyčka zpráv Zpracování zprávy Nové

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í Pokud žádné zprávy nejsou, tak čéká (blokuje)
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í Návratová hodnota je BOOL, ale
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í Přeloží zprávu - virtual-keys -> char
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í Doručí zprávu proceduře daného okna
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 Pošle zprávu danému oknu
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 Pošle zprávu danému oknu
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 Obsluhuje zprávy poslané danému oknu
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 <windows.h>
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); BOOL code; MSG msg; while((code=GetMessage(&msg,NULL,0,0))!= 0) if (code==-1) return -1; TranslateMessage(&msg); DispatchMessage(&msg); return (int) msg.wParam;

31 if(!RegisterClassEx(&wc)) return -1;
#include <windows.h> HWND button; 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); BOOL code; MSG msg; 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 Každý dialog má okenní proceduru
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 Dialogy - příklad Automaticky vygenerovaný soubor resource1.h
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by GUI_HelloWorld1.rc // #define IDD_DIALOG #define IDC_EDIT // Next default values for new objects #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE #define _APS_NEXT_COMMAND_VALUE #define _APS_NEXT_CONTROL_VALUE #define _APS_NEXT_SYMED_VALUE #endif

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

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, 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); BOOL code; MSG msg; 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 <windows.h>
#include "resource1.h" HWND button; HWND dialog=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 Win 32 API"

Podobné prezentace


Reklamy Google