12.1.2002
V minulých dílech jsme si ukázali na jednoduchém příkladě editačního pole a tlačítka, jak vytvořit tzv. Běžné prvky Windows na nějakém rodičovském okně, které pak přijímá zprávy od těchto prvků, týkající se především uživatelského vstupu. Ve standardních programech se většinou takovéto prvky umísťují na dialogová okna. Tímto výrazem mám na mysli dialogová okna v pravém slova smyslu, tedy nikoli okna chovající se jako dialog. Z hlediska Win API jsou totiž dialogy speciální třídou oken, mající některé specifické vlastnosti odlišující je od oken, jako je třeba hlavní okno naší aplikace. Jaké jsou tedy hlavní rozdíly? Pro vlastní dialogové okno neregistrujeme vlastní třídu. Dialogy totiž patří do třídy, která je již zaregistrovaná (podobně jako jsme tvořili edit-box a button). Mají také proceduru okna, která má stejné parametry jako "běžná" procedura okna, avšak její návratovou hodnotou v případě požadavku na výchozí zpracování zprávy není výsledek funkce DefWindowProc, jako u "klasického" okna, ale pouze vrátíme FALSE pokud se má zpráva zpracovat defautlně a TRUE, pokud je zpráva zpracovaná v aplikaci. Dále dialogové okno můžeme vytvořit jako modální nebo nemodální. Modální dialog běžně vytváříme (a zobrazujeme) funkcí DialogBox:INT_PTR DialogBox( HINSTANCE hInstance, // handle modulu(instance) LPCTSTR lpTemplate, // název zdroje dialogu HWND hWndParent, // handle rodičovského okna DLGPROC lpDialogFunc // procedura okna dialogu );Pokud chceme vytvořit nemodální dialogové okno, použijeme funkci CreateDialog:
HWND CreateDialog( HINSTANCE hInstance, // handle instance LPCTSTR lpTemplate, // název zdroje dialogu HWND hWndParent, // handle rodičovského okna DLGPROC lpDialogFunc // procedure okna dialogu );Tato funkce nám vrátí handle okna vytvořeného dialogu, které pak zobrazíme funkcí ShowWindow stejně jako "bežné" okno. Takový dialog je pak nemodální, to znamená, že bez jeho zavření můžeme pracovat s jiným oknem aplikace a opět se do dialogu vracet bez jeho opakovaného vytváření. V praxi ale většina dialogových oken bývá modální. Nyní vyvstane otázka, jak se dialog ukončuje. Zde je rozdíl oproti běžnému oknu. Pokud bychom totiž v proceduře dialogu sami nezařídili jeho ukončení v reakci na nějaký podnět uživatele, okno dialogu se samo nezavře ani třeba po kliknutí na systémovou ikonku "zavřít". Musíme tedy alespoň na jednom místě použít funkci EndDialog:
BOOL EndDialog( HWND hDlg, // handle okna dialogu INT_PTR nResult // návratová hodnota dialogu );Parametrem nResult určíme hodnotu, kterou pak dostaneme jako návratovou hodnotu funkce DialogBox, pokud jsme dialog vytvořili jako modální. Tímto způsobem pak můžeme rozlišit například zda uživatel ukončil dialog stisknutím tlačítka "OK" nebo "Storno". Vše si za chvilku ukážeme. Posledním významným rozdílem mezi dialogem a běžným oknem je, že prvky na dialogu (edit, list-box, button atd.) se nevytvářejí (přesněji řečeno nemusí se takto vytvářet) programově tak, jak jsme to dělali na našem hlavním okně, ale jsou vytvořeny automaticky podle předpisu v skriptu zdroje resource skript). Nic nám samozřejmě nebrání abychom po vytvoření dialogového okna stejným způsobem přidali další prvky (pomocí CreateWindowEx), ale v praxi se to nedělá, pokud k tomu není nějaký zvláštní důvod. Ukažme si nyní vše na příkladě. V editoru zdrojů si vytvoříme dialog (zde nazvaný IDD_DIALOG1), zatím pouze s tlačítky "OK" a "Cancel", která mají identifikátory IDOK a IDCANCEL (které ve Visual C++ jsou takto nazvány defaultně). Dále si napíšeme následující (zatím tu nejjednodušší) proceduru dialogu:
INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch ( uMsg ) { case WM_COMMAND: switch ( LOWORD(wParam) ) { case IDOK: EndDialog(hwndDlg, IDOK); break; case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; } break; } return FALSE; }Jak je vidět, zachytávání "příkazové" zprávy WM_COMMAND je stejné jako v případě bežného okna. V reakci na stisknutí jednoho z tlačítek pak dialog ukončíme zmíněnou funkcí EndDialog s předáním identifikátoru použitého tlačítka. Vlastní dialog pak vyvoláme (v proceduře hlavního okna) na výběr položky, kterou si přidáme do nabídky hlavního okna:
case WM_COMMAND: switch ( LOWORD(wParam) ) { // ostastní příkazy.... case ID_SHOW_DIALOG: dlgResult = DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hwnd, (DLGPROC)DialogProc); if ( dlgResult == IDOK ) MessageBox(hwnd, "Dialog ukončen OK", "Dialog", MB_ICONINFORMATION); else MessageBox(hwnd, "Dialog ukončen Cancel", "Dialog", MB_ICONEXCLAMATION); break; }Zde je také vidět jak určíme z návratové hodnoty funkce DialogBox, jakým tlačítkem byl dialog ukončen. Pro úplnost ještě dodám, že stisknutí systémové ikonky "Zavřít" v dialogu vyvolá zprávu s identifikátorem IDCANCEL, proto je výhodné nechat identifikátor tlačítka quot;Storno" takto nazvaný abychom nemuseli testovat každý případ zvlášť. Doprovodný projekt je ke stažení zde: win_api_12.zip
Školení
Kontakt
739 219 991
live:radekchalupa_1
Nové články