9. Modális párbeszéd ablakok (Modeless dialogs)
2014.06.07. 22:45
Példa: dlg_two
A CreateDialog() nagyban hasonlít a DialogBox()-hoz, de van egy lényeges különbség közöttük. A DialogBox() mint azt az előző fejezetben láttuk saját üzenethurokkal rendelkezik, és nem is tér vissza, amíg az ablakát be nem zárjuk. A CreateDialog() ezzel szemben azonnal visszatér, és a fő ablak üzeneteit eszi. Létrehozhatunk ilyet erőforrásként mint ahogyan azt az előző példában tettük, így készíthetünk "eszköztárat".
IDD_TOOLBAR DIALOGEX 0, 0, 98, 52 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION EXSTYLE WS_EX_TOOLWINDOW CAPTION "My Dialog Toolbar" FONT 8, "MS Sans Serif" BEGIN PUSHBUTTON "&Press This Button",IDC_PRESS,7,7,84,14 PUSHBUTTON "&Or This One",IDC_OTHER,7,31,84,14 END
Létre kell hozzunk egy globális változót, amiben a CreateDialog() által visszaadott handlert fogjuk tárolni. Erre azért van szükség, hogy később tudjunk rá hivatkozni. A DialogBox() nem ad vissza handlert, mert az az ablak bezárásával semmisül meg.
HWND g_hToolbar = NULL;
case WM_CREATE: g_hToolbar = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_TOOLBAR), hwnd, ToolDlgProc); if(g_hToolbar != NULL) { ShowWindow(g_hToolbar, SW_SHOW); } else { MessageBox(hwnd, "CreateDialog returned NULL", "Warning!", MB_OK | MB_ICONINFORMATION); } break;
Mindig ellenőrízzük a visszatérési értéket, és ha az nem NULL, akkor az ablakunkat a ShowWindow() segítségével meg tudjuk jeleníteni. A DialogBox() nem kéri a ShowWindow() hívását, mert a rendszer ezt automatikusan megteszi helyettünk.
A toolbar-unknak szüksége van egy kezelő eljárásra:
BOOL CALLBACK ToolDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { switch(Message) { case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_PRESS: MessageBox(hwnd, "Hi!", "This is a message", MB_OK | MB_ICONEXCLAMATION); break; case IDC_OTHER: MessageBox(hwnd, "Bye!", "This is also a message", MB_OK | MB_ICONEXCLAMATION); break; } break; default: return FALSE; } return TRUE; }
Ugyanazok az üzenetkezelési szabályok igazak a CreateDialog()-ra, mint a DialogBox() esetén. Nem hívjuk meg a DefWindowProc() eljárást. Ha eldobjuk az üzenetet, akkor FALSE a visszatérési érték, ha viszont feldolgozzuk, akkor TRUE.
Eltérés, hogy nem hívjuk meg az EndDialog() eljárást, helyette a DestroyWindow() használható. Ebben az esetben a párbeszéd ablak a fő ablakkal együtt záródik.
A fő ablak WndProc() részlete:
case WM_DESTROY: DestroyWindow(g_hToolbar); PostQuitMessage(0); break;
Szeretnénk olyat, hogy gombnyomásra megjelenjen, és eltűnjön az eszköztárunk:
case WM_COMMAND: switch(LOWORD(wParam)) { case ID_DIALOG_SHOW: ShowWindow(g_hToolbar, SW_SHOW); break; case ID_DIALOG_HIDE: ShowWindow(g_hToolbar, SW_HIDE); break; //... other command handlers } break;
Elvileg most már egyszerre van egy párbeszéd ablakunk, és egy fő ablakunk is. Majdnem jó, de hiába nyomkodjuk az Alt+O, Alt+P billentyűket, semmi sem történik. A DialogBox() tudja a saját üzeneteit alapból kezelni, de a CreateDialog() sajnos nem. Szerencsére meg tudjuk oldani magunk a dolgot, ha az IsDialogMessage()-t hívjuk az alkalmazás fő eseményhurkában.
while(GetMessage(&Msg, NULL, 0, 0)) { if(!IsDialogMessage(g_hToolbar, &Msg)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } }
Az IsDialogMessage() kapja meg először az üzenetet (az hogy neki szól-e, az első paraméterben kapott handlertől tudja). Eldönti hogy feldolgozza-e. Ha igen, akkor TRUE értékkel tér vissza. Ebben az esetben már nem foglalkozunk vele tovább, hiszen az üzenetet már feldolgozták.
A bejegyzés trackback címe:
Kommentek:
A hozzászólások a vonatkozó jogszabályok értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a Felhasználási feltételekben és az adatvédelmi tájékoztatóban.