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...

This commit is contained in:
Pietro Gagliardi 2015-11-28 10:53:48 -05:00
parent 0bcd620a62
commit e6e264408f
8 changed files with 27 additions and 159 deletions

View File

@ -37,7 +37,6 @@ CFILES += \
windows/control.c \ windows/control.c \
windows/datetimepicker.c \ windows/datetimepicker.c \
windows/debug.c \ windows/debug.c \
windows/dialoghelper.c \
windows/draw.c \ windows/draw.c \
windows/entry.c \ windows/entry.c \
windows/events.c \ windows/events.c \

View File

@ -45,11 +45,14 @@ static void openAnotherWindow(uiButton *bb, void *data)
uiBox *b; uiBox *b;
w = uiNewWindow("Another Window", 100, 100, data != NULL); w = uiNewWindow("Another Window", 100, 100, data != NULL);
if (data != NULL) {
b = uiNewVerticalBox(); b = uiNewVerticalBox();
uiBoxAppend(b, uiControl(uiNewEntry()), 0); uiBoxAppend(b, uiControl(uiNewEntry()), 0);
uiBoxAppend(b, uiControl(uiNewButton("Button")), 0); uiBoxAppend(b, uiControl(uiNewButton("Button")), 0);
uiBoxSetPadded(b, 1); uiBoxSetPadded(b, 1);
uiWindowSetChild(w, uiControl(b)); uiWindowSetChild(w, uiControl(b));
} else
uiWindowSetChild(w, uiControl(makePage6()));
uiWindowSetMargined(w, 1); uiWindowSetMargined(w, 1);
uiControlShow(uiControl(w)); uiControlShow(uiControl(w));
} }

View File

@ -12,7 +12,6 @@ CFILES += \
windows/control.c \ windows/control.c \
windows/datetimepicker.c \ windows/datetimepicker.c \
windows/debug.c \ windows/debug.c \
windows/dialoghelper.c \
windows/draw.c \ windows/draw.c \
windows/entry.c \ windows/entry.c \
windows/events.c \ windows/events.c \

View File

@ -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()");
}

View File

@ -146,9 +146,6 @@ const char *uiInit(uiInitOptions *o)
if (InitCommonControlsEx(&icc) == 0) if (InitCommonControlsEx(&icc) == 0)
return loadLastError("initializing Common Controls"); return loadLastError("initializing Common Controls");
if (initDialogHelper(hDefaultIcon, hDefaultCursor) == 0)
return loadLastError("initializing the dialog helper");
hr = CoInitialize(NULL); hr = CoInitialize(NULL);
if (hr != S_OK && hr != S_FALSE) if (hr != S_OK && hr != S_FALSE)
return loadHRESULT("initializing COM", hr); return loadHRESULT("initializing COM", hr);
@ -173,7 +170,6 @@ void uiUninit(void)
unregisterArea(); unregisterArea();
uninitDraw(); uninitDraw();
CoUninitialize(); CoUninitialize();
uninitDialogHelper();
if (DeleteObject(hollowBrush) == 0) if (DeleteObject(hollowBrush) == 0)
logLastError("error freeing hollow brush in uiUninit()"); logLastError("error freeing hollow brush in uiUninit()");
if (SetConsoleCtrlHandler(consoleCtrlHandler, FALSE) == 0) if (SetConsoleCtrlHandler(consoleCtrlHandler, FALSE) == 0)

View File

@ -7,12 +7,14 @@
// TODO // TODO
// - http://blogs.msdn.com/b/wpfsdk/archive/2006/10/26/uncommon-dialogs--font-chooser-and-color-picker-dialogs.aspx // - 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; IFileDialog *d;
FILEOPENDIALOGOPTIONS opts; FILEOPENDIALOGOPTIONS opts;
HWND dialogHelper;
IShellItem *result; IShellItem *result;
WCHAR *wname; WCHAR *wname;
char *name; char *name;
@ -30,9 +32,7 @@ char *commonItemDialog(REFCLSID clsid, REFIID iid, FILEOPENDIALOGOPTIONS optsadd
hr = IFileDialog_SetOptions(d, opts); hr = IFileDialog_SetOptions(d, opts);
if (hr != S_OK) if (hr != S_OK)
logHRESULT("error setting options in commonItemDialog()", hr); logHRESULT("error setting options in commonItemDialog()", hr);
dialogHelper = beginDialogHelper(); hr = IFileDialog_Show(d, parent);
hr = IFileDialog_Show(d, dialogHelper);
endDialogHelper(dialogHelper);
if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) { if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
IFileDialog_Release(d); IFileDialog_Release(d);
return NULL; return NULL;
@ -52,44 +52,45 @@ char *commonItemDialog(REFCLSID clsid, REFIID iid, FILEOPENDIALOGOPTIONS optsadd
return name; 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); 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? // TODO strip FOS_NOREADONLYRETURN?
FOS_OVERWRITEPROMPT | FOS_NOCHANGEDIR | FOS_ALLNONSTORAGEITEMS | FOS_NOVALIDATE | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_NODEREFERENCELINKS | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE); 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; WCHAR *wtitle, *wdescription;
HWND dialogHelper;
HRESULT hr; HRESULT hr;
wtitle = toUTF16(title); wtitle = toUTF16(title);
wdescription = toUTF16(description); wdescription = toUTF16(description);
dialogHelper = beginDialogHelper(); hr = TaskDialog(parent, NULL, NULL, wtitle, wdescription, buttons, icon, NULL);
hr = TaskDialog(dialogHelper, NULL, NULL, wtitle, wdescription, buttons, icon, NULL);
if (hr != S_OK) if (hr != S_OK)
logHRESULT("error showing task dialog in msgbox()", hr); logHRESULT("error showing task dialog in msgbox()", hr);
endDialogHelper(dialogHelper);
uiFree(wdescription); uiFree(wdescription);
uiFree(wtitle); 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);
} }

View File

@ -89,14 +89,6 @@ extern BOOL runWM_NOTIFY(WPARAM, LPARAM, LRESULT *);
extern BOOL runWM_HSCROLL(WPARAM, LPARAM, LRESULT *); extern BOOL runWM_HSCROLL(WPARAM, LPARAM, LRESULT *);
extern void issueWM_WININICHANGE(WPARAM, LPARAM); 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 // child.c
extern struct child *newChild(uiControl *child, uiControl *parent, HWND parentHWND); extern struct child *newChild(uiControl *child, uiControl *parent, HWND parentHWND);
extern struct child *newChildWithTabPage(uiControl *child, uiControl *parent, HWND parentHWND); extern struct child *newChildWithTabPage(uiControl *child, uiControl *parent, HWND parentHWND);

View File

@ -120,8 +120,6 @@ static void onDestroy(uiWindow *w)
// now free the menubar, if any // now free the menubar, if any
if (w->menubar != NULL) if (w->menubar != NULL)
freeMenubar(w->menubar); freeMenubar(w->menubar);
// and finally destroy ourselves
dialogHelperUnregisterWindow(w->hwnd);
} }
static void windowCommitShow(uiControl *c) 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()"); logLastError("error creating window in uiWindow()");
uiFree(wtitle); uiFree(wtitle);
dialogHelperRegisterWindow(w->hwnd);
if (hasMenubar) { if (hasMenubar) {
w->menubar = makeMenubar(); w->menubar = makeMenubar();
if (SetMenu(w->hwnd, w->menubar) == 0) if (SetMenu(w->hwnd, w->menubar) == 0)