From e6e264408f21912580d869eb30e5951e19fc1d07 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sat, 28 Nov 2015 10:53:48 -0500 Subject: [PATCH] Implemented dialog parenting on Windows. Eliminated the dialog helper. uiArea still works (and still responds to key events), but IsDialogMessage() isn't being called for the active window anymore... --- GNUmakefile.msvc | 1 - test/page2.c | 13 +++-- windows/GNUmakeinc.mk | 1 - windows/dialoghelper.c | 118 --------------------------------------- windows/init.c | 4 -- windows/stddialogs.c | 37 ++++++------ windows/uipriv_windows.h | 8 --- windows/window.c | 4 -- 8 files changed, 27 insertions(+), 159 deletions(-) delete mode 100644 windows/dialoghelper.c diff --git a/GNUmakefile.msvc b/GNUmakefile.msvc index 33c7b111..214c3059 100644 --- a/GNUmakefile.msvc +++ b/GNUmakefile.msvc @@ -37,7 +37,6 @@ CFILES += \ windows/control.c \ windows/datetimepicker.c \ windows/debug.c \ - windows/dialoghelper.c \ windows/draw.c \ windows/entry.c \ windows/events.c \ diff --git a/test/page2.c b/test/page2.c index 07d9d02a..abb06489 100644 --- a/test/page2.c +++ b/test/page2.c @@ -45,11 +45,14 @@ static void openAnotherWindow(uiButton *bb, void *data) uiBox *b; w = uiNewWindow("Another Window", 100, 100, data != NULL); - b = uiNewVerticalBox(); - uiBoxAppend(b, uiControl(uiNewEntry()), 0); - uiBoxAppend(b, uiControl(uiNewButton("Button")), 0); - uiBoxSetPadded(b, 1); - uiWindowSetChild(w, uiControl(b)); + if (data != NULL) { + b = uiNewVerticalBox(); + uiBoxAppend(b, uiControl(uiNewEntry()), 0); + uiBoxAppend(b, uiControl(uiNewButton("Button")), 0); + uiBoxSetPadded(b, 1); + uiWindowSetChild(w, uiControl(b)); + } else + uiWindowSetChild(w, uiControl(makePage6())); uiWindowSetMargined(w, 1); uiControlShow(uiControl(w)); } diff --git a/windows/GNUmakeinc.mk b/windows/GNUmakeinc.mk index 06f54ccf..c7c5b270 100644 --- a/windows/GNUmakeinc.mk +++ b/windows/GNUmakeinc.mk @@ -12,7 +12,6 @@ CFILES += \ windows/control.c \ windows/datetimepicker.c \ windows/debug.c \ - windows/dialoghelper.c \ windows/draw.c \ windows/entry.c \ windows/events.c \ diff --git a/windows/dialoghelper.c b/windows/dialoghelper.c deleted file mode 100644 index aeb0c25e..00000000 --- a/windows/dialoghelper.c +++ /dev/null @@ -1,118 +0,0 @@ -// 22 may 2015 -#include "uipriv_windows.h" - -// see http://stackoverflow.com/questions/25494914/is-there-something-like-cdn-filecancel-analogous-to-cdn-fileok-for-getting-when#comment40420049_25494914 - -struct dialogDisableWindow { - HWND hwnd; - uintmax_t n; - BOOL prevstate; - UT_hash_handle hh; -}; - -static struct dialogDisableWindow *windows = NULL; - -void dialogHelperRegisterWindow(HWND hwnd) -{ - struct dialogDisableWindow *d; - - HASH_FIND_PTR(windows, &hwnd, d); - if (d != NULL) - complain("window handle %p already register in dialogHelperRegisterWindow()", hwnd); - d = uiNew(struct dialogDisableWindow); - d->hwnd = hwnd; - HASH_ADD_PTR(windows, hwnd, d); -} - -void dialogHelperUnregisterWindow(HWND hwnd) -{ - struct dialogDisableWindow *d; - - HASH_FIND_PTR(windows, &hwnd, d); - if (d == NULL) - complain("window handle %p not registered in dialogHelperUnregisterWindow()", hwnd); - HASH_DEL(windows, d); - uiFree(d); -} - -static void dialogBegin(void) -{ - struct dialogDisableWindow *d; - BOOL prevstate; - - for (d = windows; d != NULL; d = d->hh.next) { - prevstate = EnableWindow(d->hwnd, FALSE); - // store the previous state in case the window was already disabled by the user - // note the !; EnableWindow() returns TRUE if window was previously /disabled/ - if (d->n == 0) - d->prevstate = !prevstate; - d->n++; - } -} - -static void dialogEnd(void) -{ - struct dialogDisableWindow *d; - - for (d = windows; d != NULL; d = d->hh.next) { - d->n--; - if (d->n == 0) - EnableWindow(d->hwnd, d->prevstate); - } -} - -#define dialogHelperClass L"libui_dialogHelperClass" - -static LRESULT CALLBACK dialogHelperWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case WM_CREATE: - dialogBegin(); - break; - case WM_ENABLE: - if (wParam != (WPARAM) FALSE) // enabling - dialogEnd(); - break; - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); -} - -ATOM initDialogHelper(HICON hDefaultIcon, HCURSOR hDefaultCursor) -{ - WNDCLASSW wc; - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = dialogHelperClass; - wc.lpfnWndProc = dialogHelperWndProc; - wc.hInstance = hInstance; - wc.hIcon = hDefaultIcon; - wc.hCursor = hDefaultCursor; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - return RegisterClassW(&wc); -} - -void uninitDialogHelper(void) -{ - if (UnregisterClassW(dialogHelperClass, hInstance) == 0) - logLastError("error unregistering dialog helper window class in uninitDialogHelper()"); -} - -HWND beginDialogHelper(void) -{ - HWND hwnd; - - hwnd = CreateWindowExW(0, - dialogHelperClass, L"libui dialog helper", - WS_OVERLAPPEDWINDOW, - 0, 0, 100, 100, - NULL, NULL, hInstance, NULL); - if (hwnd == NULL) - logLastError("error creating dialog helper in beginDialogHelper()"); - return hwnd; -} - -void endDialogHelper(HWND hwnd) -{ - if (DestroyWindow(hwnd) == 0) - logLastError("error cleaning up after dialog helper in endDialogHelper()"); -} diff --git a/windows/init.c b/windows/init.c index 4a238b79..9f866256 100644 --- a/windows/init.c +++ b/windows/init.c @@ -146,9 +146,6 @@ const char *uiInit(uiInitOptions *o) if (InitCommonControlsEx(&icc) == 0) return loadLastError("initializing Common Controls"); - if (initDialogHelper(hDefaultIcon, hDefaultCursor) == 0) - return loadLastError("initializing the dialog helper"); - hr = CoInitialize(NULL); if (hr != S_OK && hr != S_FALSE) return loadHRESULT("initializing COM", hr); @@ -173,7 +170,6 @@ void uiUninit(void) unregisterArea(); uninitDraw(); CoUninitialize(); - uninitDialogHelper(); if (DeleteObject(hollowBrush) == 0) logLastError("error freeing hollow brush in uiUninit()"); if (SetConsoleCtrlHandler(consoleCtrlHandler, FALSE) == 0) diff --git a/windows/stddialogs.c b/windows/stddialogs.c index c2714466..859ec320 100644 --- a/windows/stddialogs.c +++ b/windows/stddialogs.c @@ -7,12 +7,14 @@ // TODO // - http://blogs.msdn.com/b/wpfsdk/archive/2006/10/26/uncommon-dialogs--font-chooser-and-color-picker-dialogs.aspx +// - when a dialog is active, tab navigation in other windows stops working -char *commonItemDialog(REFCLSID clsid, REFIID iid, FILEOPENDIALOGOPTIONS optsadd) +#define windowHWND(w) ((HWND) uiControlHandle(uiControl(w))) + +char *commonItemDialog(HWND parent, REFCLSID clsid, REFIID iid, FILEOPENDIALOGOPTIONS optsadd) { IFileDialog *d; FILEOPENDIALOGOPTIONS opts; - HWND dialogHelper; IShellItem *result; WCHAR *wname; char *name; @@ -30,9 +32,7 @@ char *commonItemDialog(REFCLSID clsid, REFIID iid, FILEOPENDIALOGOPTIONS optsadd hr = IFileDialog_SetOptions(d, opts); if (hr != S_OK) logHRESULT("error setting options in commonItemDialog()", hr); - dialogHelper = beginDialogHelper(); - hr = IFileDialog_Show(d, dialogHelper); - endDialogHelper(dialogHelper); + hr = IFileDialog_Show(d, parent); if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) { IFileDialog_Release(d); return NULL; @@ -52,44 +52,45 @@ char *commonItemDialog(REFCLSID clsid, REFIID iid, FILEOPENDIALOGOPTIONS optsadd return name; } -char *uiOpenFile(void) +char *uiOpenFile(uiWindow *parent) { - return commonItemDialog(&CLSID_FileOpenDialog, &IID_IFileOpenDialog, + return commonItemDialog(windowHWND(parent), + &CLSID_FileOpenDialog, &IID_IFileOpenDialog, FOS_NOCHANGEDIR | FOS_ALLNONSTORAGEITEMS | FOS_NOVALIDATE | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_NODEREFERENCELINKS | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE); } -char *uiSaveFile(void) +char *uiSaveFile(uiWindow *parent) { - return commonItemDialog(&CLSID_FileSaveDialog, &IID_IFileSaveDialog, + return commonItemDialog(windowHWND(parent), + &CLSID_FileSaveDialog, &IID_IFileSaveDialog, // TODO strip FOS_NOREADONLYRETURN? FOS_OVERWRITEPROMPT | FOS_NOCHANGEDIR | FOS_ALLNONSTORAGEITEMS | FOS_NOVALIDATE | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_NODEREFERENCELINKS | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE); } -static void msgbox(const char *title, const char *description, TASKDIALOG_COMMON_BUTTON_FLAGS buttons, PCWSTR icon) +// TODO switch to TaskDialogIndirect()? + +static void msgbox(HWND parent, const char *title, const char *description, TASKDIALOG_COMMON_BUTTON_FLAGS buttons, PCWSTR icon) { WCHAR *wtitle, *wdescription; - HWND dialogHelper; HRESULT hr; wtitle = toUTF16(title); wdescription = toUTF16(description); - dialogHelper = beginDialogHelper(); - hr = TaskDialog(dialogHelper, NULL, NULL, wtitle, wdescription, buttons, icon, NULL); + hr = TaskDialog(parent, NULL, NULL, wtitle, wdescription, buttons, icon, NULL); if (hr != S_OK) logHRESULT("error showing task dialog in msgbox()", hr); - endDialogHelper(dialogHelper); uiFree(wdescription); uiFree(wtitle); } -void uiMsgBox(const char *title, const char *description) +void uiMsgBox(uiWindow *parent, const char *title, const char *description) { - msgbox(title, description, TDCBF_OK_BUTTON, NULL); + msgbox(windowHWND(parent), title, description, TDCBF_OK_BUTTON, NULL); } -void uiMsgBoxError(const char *title, const char *description) +void uiMsgBoxError(uiWindow *parent, const char *title, const char *description) { - msgbox(title, description, TDCBF_OK_BUTTON, TD_ERROR_ICON); + msgbox(windowHWND(parent), title, description, TDCBF_OK_BUTTON, TD_ERROR_ICON); } diff --git a/windows/uipriv_windows.h b/windows/uipriv_windows.h index b8386084..4c605b18 100644 --- a/windows/uipriv_windows.h +++ b/windows/uipriv_windows.h @@ -89,14 +89,6 @@ extern BOOL runWM_NOTIFY(WPARAM, LPARAM, LRESULT *); extern BOOL runWM_HSCROLL(WPARAM, LPARAM, LRESULT *); extern void issueWM_WININICHANGE(WPARAM, LPARAM); -// dialoghelper.c -extern void dialogHelperRegisterWindow(HWND); -extern void dialogHelperUnregisterWindow(HWND); -extern ATOM initDialogHelper(HICON, HCURSOR); -extern void uninitDialogHelper(void); -extern HWND beginDialogHelper(void); -extern void endDialogHelper(HWND); - // child.c extern struct child *newChild(uiControl *child, uiControl *parent, HWND parentHWND); extern struct child *newChildWithTabPage(uiControl *child, uiControl *parent, HWND parentHWND); diff --git a/windows/window.c b/windows/window.c index 63362342..ca2e0652 100644 --- a/windows/window.c +++ b/windows/window.c @@ -120,8 +120,6 @@ static void onDestroy(uiWindow *w) // now free the menubar, if any if (w->menubar != NULL) freeMenubar(w->menubar); - // and finally destroy ourselves - dialogHelperUnregisterWindow(w->hwnd); } static void windowCommitShow(uiControl *c) @@ -288,8 +286,6 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) logLastError("error creating window in uiWindow()"); uiFree(wtitle); - dialogHelperRegisterWindow(w->hwnd); - if (hasMenubar) { w->menubar = makeMenubar(); if (SetMenu(w->hwnd, w->menubar) == 0)