diff options
| author | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-05-30 17:52:50 +0200 |
|---|---|---|
| committer | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-05-30 17:52:50 +0200 |
| commit | 90c561d8e2d0693890f58167a30eca84509262ba (patch) | |
| tree | cc3fa8ee99dda18e7a228794c5176e9c613c0895 | |
| parent | 379e9fd3a72fbf5f136443284bc6a2d81bb828fa (diff) | |
fixup and test modal dialog
| -rw-r--r-- | alf/alf.h | 4 | ||||
| -rw-r--r-- | alf/alftoplevel.cpp | 87 | ||||
| -rw-r--r-- | widgetfactory.cpp | 80 |
3 files changed, 131 insertions, 40 deletions
@@ -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; } diff --git a/widgetfactory.cpp b/widgetfactory.cpp index c7f5f8d..060544b 100644 --- a/widgetfactory.cpp +++ b/widgetfactory.cpp @@ -38,7 +38,9 @@ enum { IDM_BACKGROUND_GREEN, IDM_BACKGROUND_BLUE, IDM_PANES, - IDM_PANES__MAX = IDM_PANES + PANE__MAX + IDM_PANES__MAX = IDM_PANES + PANE__MAX, + IDM_MODALDIALOG_PANES, + IDM_MODALDIALOG_PANES__MAX = IDM_MODALDIALOG_PANES + PANE__MAX }; BOOL (WINAPI *fnGradientFill)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG) = NULL; @@ -52,6 +54,8 @@ enum PanelBackgroundMode { #define FM_PANEL_SET_BGMODE (ALF_WM_USER + 1) +static void wfModalDialogRun(HWND owner, int pane); + /* common stuff */ typedef struct { DWORD bgmode; @@ -740,6 +744,14 @@ addPaneToNotebook(HWND hwndNotebook, int paneId) g_paneInitTable[paneId](panel); } +static void +handleClose(void *closure, HWND window) +{ + (void)closure; + + ALF_Toplevel_SetModalResult(window, 0); +} + static LRESULT handleCommand(void *closure, HWND window, WORD notificationcode, WORD sourceid, HWND control) { @@ -802,9 +814,67 @@ handleCommand(void *closure, HWND window, WORD notificationcode, WORD sourceid, addPaneToNotebook(nb, paneId); } + if (sourceid >= IDM_MODALDIALOG_PANES && sourceid < IDM_MODALDIALOG_PANES__MAX) { + int paneId = sourceid - IDM_MODALDIALOG_PANES; + wfModalDialogRun(window, paneId); + } + return 0; } +static BOOL +wfModalDialogInit(void *closure, HWND dialog) +{ + HWND panel = ALF_AddPanel(dialog, (WORD)-1, 1, 1); + int paneid = (int)(LONG_PTR)closure; + g_paneInitTable[paneid](panel); + + ALF_SetText(dialog, g_paneLabels[paneid]); + + ALF_LayoutSetColumnExpandNumerator(dialog, 1, 1); + ALF_LayoutSetRowExpandNumerator(dialog, 1, 1); + ALF_LayoutSetRowMinSize(dialog, 0, 525); + ALF_LayoutSetRowMinSize(dialog, 2, 525); + ALF_LayoutSetColumnMinSize(dialog, 0, 525); + ALF_LayoutSetColumnMinSize(dialog, 2, 525); + + return TRUE; +} + +static LRESULT +wfModalDialogWindowProc(void *closure, HWND dialog, UINT msg, WPARAM wp, LPARAM lp) +{ + (void)closure; + + if (msg == WM_CLOSE) { + ALF_Toplevel_SetModalResult(dialog, 0); + } + + return ALF_Toplevel_DefWindowProc(dialog, msg, wp, lp); +} + +static ALFToplevelVTable g_wfModalDialogVtbl; + +static void +wfModalDialogPrepareVtbl(void) +{ + ZeroMemory(&g_wfModalDialogVtbl, sizeof(g_wfModalDialogVtbl)); + g_wfModalDialogVtbl.message = wfModalDialogWindowProc; + g_wfModalDialogVtbl.initialize = wfModalDialogInit; +} + +static void +wfModalDialogRun(HWND owner, int pane) +{ + HWND dlg = ALF_CreateToplevelWindow(WS_EX_DLGMODALFRAME, + WS_POPUPWINDOW | WS_CAPTION | WS_THICKFRAME, + owner, + &g_wfModalDialogVtbl, + (void*)(LONG_PTR)pane); + ALF_Toplevel_ShowModal(dlg); + DestroyWindow(dlg); +} + int CALLBACK #ifdef UNICODE wWinMain @@ -827,14 +897,17 @@ WinMain } } + wfModalDialogPrepareVtbl(); + ALFToplevelVTable vtbl; ZeroMemory(&vtbl, sizeof(vtbl)); vtbl.command = handleCommand; + vtbl.close = handleClose; ALF_Initialize(); - HWND win = ALF_CreateToplevelWindow(NULL, &vtbl, NULL); + HWND win = ALF_CreateToplevelWindow(0, WS_OVERLAPPEDWINDOW, NULL, &vtbl, NULL); if (!win) { MessageBox(0, TEXT("couldn't create main window!"), 0, MB_ICONHAND|MB_OK); return 1; @@ -870,12 +943,14 @@ WinMain HMENU mainmenu = CreateMenu(); HMENU filemenu = CreateMenu(); HMENU newtabmn = CreateMenu(); + HMENU modwndmn = CreateMenu(); HMENU helpmenu = CreateMenu(); HMENU bgmenu = CreateMenu(); AppendMenu(filemenu, MF_STRING, ID_HELLO, TEXT("Hello")); AppendMenu(filemenu, MF_SEPARATOR, 0, 0); AppendMenu(filemenu, MF_POPUP, (UINT_PTR)newtabmn, TEXT("New Tab")); + AppendMenu(filemenu, MF_POPUP, (UINT_PTR)modwndmn, TEXT("Show Modal")); AppendMenu(filemenu, MF_SEPARATOR, 0, 0); AppendMenu(filemenu, MF_STRING, IDM_FILE_CLOSE, TEXT("&Close\tAlt+F4")); @@ -892,6 +967,7 @@ WinMain for (int i = 0; i < PANE__MAX; ++i) { AppendMenu(newtabmn, MF_STRING, IDM_PANES + (UINT)i, g_paneLabels[i]); + AppendMenu(modwndmn, MF_STRING, IDM_MODALDIALOG_PANES + (UINT)i, g_paneLabels[i]); } SetMenu(win, mainmenu); |
