From 90c561d8e2d0693890f58167a30eca84509262ba Mon Sep 17 00:00:00 2001 From: Jonas Kümmerlin Date: Sat, 30 May 2020 17:52:50 +0200 Subject: fixup and test modal dialog --- alf/alf.h | 4 +-- alf/alftoplevel.cpp | 87 +++++++++++++++++++++++++++++++---------------------- 2 files changed, 53 insertions(+), 38 deletions(-) (limited to 'alf') diff --git a/alf/alf.h b/alf/alf.h index cb2e48e..6f42f35 100644 --- a/alf/alf.h +++ b/alf/alf.h @@ -10,7 +10,7 @@ extern "C" { typedef struct { BOOL (*initialize)(void * /*closure*/, HWND /*window*/); // return FALSE if you set the focus, TRUE if you want default initial focus void (*destroy)(void * /*closure*/, HWND /*window*/); - BOOL (*close)(void * /*closure*/, HWND /*window*/); + void (*close)(void * /*closure*/, HWND /*window*/); void (*postdestroy)(void * /*closure*/); LRESULT (*message)(void * /*closure*/, HWND, UINT, WPARAM, LPARAM); LRESULT (*command)(void * /*closure*/, HWND /*window*/, WORD /*notificationcode*/, WORD /*sourceid*/, HWND /*control*/); @@ -304,7 +304,7 @@ ALF_DestroyWidget(HWND win, WORD id); // toplevel window HWND -ALF_CreateToplevelWindow(HWND hwndParent, ALFToplevelVTable *vtbl, void *closure); +ALF_CreateToplevelWindow(DWORD exstyle, DWORD style, HWND hwndOwner, ALFToplevelVTable *vtbl, void *closure); void ALF_Toplevel_Resize(HWND win, int cptWidth, int cptHeight); diff --git a/alf/alftoplevel.cpp b/alf/alftoplevel.cpp index 99f78e5..161a738 100644 --- a/alf/alftoplevel.cpp +++ b/alf/alftoplevel.cpp @@ -1,8 +1,11 @@ #include "alfpriv.h" +#define ALF_TOPLEVEL_FLAG_MODALEND ((DWORD)1) + typedef struct { ALFToplevelVTable *vtbl; void *closure; + DWORD flags; LPARAM modalResult; ALFLayout layout; HWND hwndFocus; @@ -74,19 +77,14 @@ ALF_UpdateFontsPriv(HWND win, ALFToplevelPriv *priv) } -/*static BOOL -ALF_PreTranslateMessagePriv(HWND win, ALFToplevelPriv *priv, MSG *message) +BOOL +ALF_Toplevel_PreTranslateMessage(HWND toplevel, MSG *message) { - BOOL ret = FALSE; - - if (priv->vtbl->pretranslatemessage) - ret = priv->vtbl->pretranslatemessage(priv->closure, win, message); + ALFToplevelPriv *priv = (ALFToplevelPriv *)GetWindowLongPtr(toplevel, DLGWINDOWEXTRA); - if (!ret) - ret = IsDialogMessage(win, message); - - return ret; -}*/ + return (priv->vtbl && priv->vtbl->pretranslatemessage && priv->vtbl->pretranslatemessage(priv->closure, toplevel, message)) + || IsDialogMessage(toplevel, message); +} void ALF_Toplevel_EnsureBigEnough(HWND toplevel) @@ -184,6 +182,7 @@ ALF_Toplevel_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) } if (msg == ALF_WM_SETMODALRESULT) { priv->modalResult = lparam; + priv->flags |= ALF_TOPLEVEL_FLAG_MODALEND; return 0; } @@ -319,11 +318,10 @@ ALF_Toplevel_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) } if (msg == WM_CLOSE) { - if (!priv->vtbl || !priv->vtbl->close || !priv->vtbl->close(priv->closure, hwnd)) { - priv->modalResult = 2; - ShowWindow(hwnd, FALSE); - } - return TRUE; + if (priv->vtbl && priv->vtbl->close) + priv->vtbl->close(priv->closure, hwnd); + + return 0; } if (msg == WM_NCDESTROY) { @@ -399,7 +397,7 @@ ALF_UnregisterToplevelClass(void) } HWND -ALF_CreateToplevelWindow(HWND hwndParent, ALFToplevelVTable *vtbl, void *closure) +ALF_CreateToplevelWindow(DWORD exstyle, DWORD style, HWND hwndOwner, ALFToplevelVTable *vtbl, void *closure) { #pragma pack(push, 1) struct { @@ -408,8 +406,8 @@ ALF_CreateToplevelWindow(HWND hwndParent, ALFToplevelVTable *vtbl, void *closure } t; #pragma pack(pop) ZeroMemory(&t, sizeof(t)); - t.t.style = WS_OVERLAPPEDWINDOW; - t.t.dwExtendedStyle = 0; + t.t.style = style; + t.t.dwExtendedStyle = exstyle; t.t.x = 0; t.t.y = 0; t.t.cx = 10; @@ -421,10 +419,16 @@ ALF_CreateToplevelWindow(HWND hwndParent, ALFToplevelVTable *vtbl, void *closure t.s[i+1] = _alf_toplevelClass[i]; } + if (hwndOwner == GetDesktopWindow()) + hwndOwner = NULL; + + if (hwndOwner && GetWindowLong(hwndOwner, GWL_STYLE) & WS_CHILD) + hwndOwner = GetParent(hwndOwner); + struct ALFToplevel_CreateParams params; params.vtbl = vtbl; params.closure = closure; - return CreateDialogIndirectParam(ALF_HINSTANCE, &t.t, hwndParent, ALF_Toplevel_DlgProc, (LPARAM)¶ms); + return CreateDialogIndirectParam(ALF_HINSTANCE, &t.t, hwndOwner, ALF_Toplevel_DlgProc, (LPARAM)¶ms); } void @@ -434,30 +438,41 @@ ALF_Toplevel_SetDefaultButton(HWND win, WORD id) } LPARAM -ALF_Toplevel_ShowModal(HWND win) +ALF_Toplevel_ShowModal(HWND toplevel) { - MSG msg; + ALFToplevelPriv *priv = (ALFToplevelPriv *)GetWindowLongPtr(toplevel, DLGWINDOWEXTRA); - ALF_Toplevel_SetModalResult(win, 0); + priv->flags &= ~ALF_TOPLEVEL_FLAG_MODALEND; + priv->modalResult = 0; - // TODO: disable parent window - ShowWindow(win, SW_SHOW); + HWND owner = GetWindow(toplevel, GW_OWNER); + BOOL ownerEnabled = FALSE; - while (GetMessage(&msg, NULL, 0, 0) > 0) { - // TODO: call application message hooks - // TODO: call preprocess message hook + ShowWindow(toplevel, SW_SHOW); - if (!IsDialogMessage(win, &msg)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + if (owner) + ownerEnabled = !EnableWindow(owner, FALSE); - int mr = ALF_Toplevel_GetModalResult(win); - if (mr) - return mr; + while (!(priv->flags & ALF_TOPLEVEL_FLAG_MODALEND)) { + MSG msg; + if (GetMessage(&msg, NULL, 0, 0)) { + // TODO: call app-level message filter + if (!ALF_Toplevel_PreTranslateMessage(toplevel, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } else { + PostQuitMessage((int)msg.wParam); + break; + } } - return 0; + if (owner) + EnableWindow(owner, ownerEnabled); + + ShowWindow(toplevel, SW_HIDE); + + return priv->modalResult; } -- cgit v1.2.3