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:
parent
0bcd620a62
commit
e6e264408f
|
@ -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 \
|
||||
|
|
13
test/page2.c
13
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));
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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()");
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue