diff --git a/newcontrol_windows.c b/newcontrol_windows.c index 1ff404b1..3a561c6e 100644 --- a/newcontrol_windows.c +++ b/newcontrol_windows.c @@ -1,37 +1,35 @@ // 6 april 2015 #include "uipriv_windows.h" -typedef struct uiSingleHWNDControl uiSingleHWNDControl; +typedef struct singleHWND singleHWND; struct uiSingleHWNDControl { - uiControl control; HWND hwnd; - BOOL (*onWM_COMMAND)(uiControl *, WPARAM, LPARAM, void *, LRESULT *); - BOOL (*onWM_NOTIFY)(uiControl *, WPARAM, LPARAM, void *, LRESULT *); - void (*onWM_DESTROY)(uiControl *, void *); - void *onCommandNotifyDestroyData; - void (*preferredSize)(uiControl *, int, int, LONG, intmax_t *, intmax_t *); - void *data; + BOOL (*onWM_COMMAND)(uiControl *, WPARAM, LPARAM, LRESULT *); + BOOL (*onWM_NOTIFY)(uiControl *, WPARAM, LPARAM, LRESULT *); + void (*onWM_DESTROY)(uiControl *); uintptr_t parent; }; -#define S(c) ((uiSingleHWNDControl *) (c)) - static void singleDestroy(uiControl *c) { - if (DestroyWindow(S(c)->hwnd) == 0) + singleHWND *s = (singleHWND *) (c->internal); + + if (DestroyWindow(s->hwnd) == 0) logLastError("error destroying control in singleDestroy()"); - // the uiSingleHWNDControl is destroyed in the subclass procedure + // the data structures are destroyed in the subclass procedure } static uintptr_t singleHandle(uiControl *c) { - return (uintptr_t) (S(c)->hwnd); + singleHWND *s = (singleHWND *) (c->internal); + + return (uintptr_t) (s->hwnd); } static void singleSetParent(uiControl *c, uintptr_t parent) { - uiSingleHWNDControl *s = S(c); + singleHWND *s = (singleHWND *) (c->internal); s->parent = parent; if (SetParent(s->hwnd, (HWND) (s->parent)) == NULL) @@ -41,7 +39,7 @@ static void singleSetParent(uiControl *c, uintptr_t parent) static void singleRemoveParent(uiControl *c) { - uiSingleHWNDControl *s = S(c); + singleHWND *s = (singleHWND *) (c->internal); uintptr_t oldparent; oldparent = s->parent; @@ -51,38 +49,32 @@ static void singleRemoveParent(uiControl *c) updateParent(oldparent); } -static uiSize singlePreferredSize(uiControl *c, uiSizing *d) -{ - uiSize size; - - (*(S(c)->preferredSize))(c, - d->baseX, d->baseY, d->internalLeading, - &(size.width), &(size.height)); - return size; -} - static void singleResize(uiControl *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) { - if (MoveWindow(S(c)->hwnd, x, y, width, height, TRUE) == 0) + singleHWND *s = (singleHWND *) (c->internal); + + if (MoveWindow(s->hwnd, x, y, width, height, TRUE) == 0) logLastError("error moving control in singleResize()"); } static LRESULT CALLBACK singleSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { - uiSingleHWNDControl *c = (uiSingleHWNDControl *) dwRefData; + uiControl *c = (uiControl *) dwRefData; + singleHWND *s = (singleHWND *) (c->internal); LRESULT lResult; switch (uMsg) { case msgCOMMAND: - if ((*(c->onWM_COMMAND))((uiControl *) c, wParam, lParam, c->onCommandNotifyDestroyData, &lResult) != FALSE) + if ((*(s->onWM_COMMAND))(c, wParam, lParam, &lResult) != FALSE) return lResult; break; case msgNOTIFY: - if ((*(c->onWM_NOTIFY))((uiControl *) c, wParam, lParam, c->onCommandNotifyDestroyData, &lResult) != FALSE) + if ((*(s->onWM_NOTIFY))(c, wParam, lParam, &lResult) != FALSE) return lResult; break; case WM_DESTROY: - (*(c->onWM_DESTROY))((uiControl *) c, c->onCommandNotifyDestroyData); + (*(s->onWM_DESTROY))(c); + uiFree(s); uiFree(c); break; case WM_NCDESTROY: @@ -95,51 +87,44 @@ static LRESULT CALLBACK singleSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, uiControl *uiWindowsNewControl(uiWindowsNewControlParams *p) { - uiSingleHWNDControl *c; + uiControl *c; + singleHWND *s; - c = uiNew(uiSingleHWNDControl); - c->hwnd = CreateWindowExW(p->dwExStyle, + s = uiNew(singleHWND); + s->hwnd = CreateWindowExW(p->dwExStyle, p->lpClassName, p->lpWindowName, p->dwStyle | WS_CHILD | WS_VISIBLE, 0, 0, 100, 100, // TODO specify control IDs properly initialParent, NULL, p->hInstance, NULL); - if (c->hwnd == NULL) + if (s->hwnd == NULL) logLastError("error creating control in uiWindowsNewControl()"); + s->onWM_COMMAND = p->onWM_COMMAND; + s->onWM_NOTIFY = p->onWM_NOTIFY; + s->onWM_DESTROY = p->onWM_DESTROY; - c->control.destroy = singleDestroy; - c->control.handle = singleHandle; - c->control.setParent = singleSetParent; - c->control.removeParent = singleRemoveParent; - c->control.preferredSize = singlePreferredSize; - c->control.resize = singleResize; + c = uiNew(uiControl); + c->internal = s; + c->destroy = singleDestroy; + c->handle = singleHandle; + c->setParent = singleSetParent; + c->removeParent = singleRemoveParent; + c->resize = singleResize; - c->onWM_COMMAND = p->onWM_COMMAND; - c->onWM_NOTIFY = p->onWM_NOTIFY; - c->onWM_DESTROY = p->onWM_DESTROY; - c->onCommandNotifyDestroyData = p->onCommandNotifyDestroyData; - c->preferredSize = p->preferredSize; - - c->data = p->data; - - if ((*fv_SetWindowSubclass)(c->hwnd, singleSubclassProc, 0, (DWORD_PTR) c) == FALSE) + if ((*fv_SetWindowSubclass)(s->hwnd, singleSubclassProc, 0, (DWORD_PTR) c) == FALSE) logLastError("error subclassing Windows control in uiWindowsNewControl()"); - return (uiControl *) c; -} - -void *uiWindowsControlData(uiControl *c) -{ - return S(c)->data; + return c; } char *uiWindowsControlText(uiControl *c) { + singleHWND *s = (singleHWND *) (c->internal); WCHAR *wtext; char *text; - wtext = windowText(S(c)->hwnd); + wtext = windowText(s->hwnd); text = toUTF8(wtext); uiFree(wtext); return text; @@ -147,10 +132,11 @@ char *uiWindowsControlText(uiControl *c) void uiWindowsControlSetText(uiControl *c, const char *text) { + singleHWND *s = (singleHWND *) (c->internal); WCHAR *wtext; wtext = toUTF16(text); - if (SetWindowTextW(S(c)->hwnd, wtext) == 0) + if (SetWindowTextW(s->hwnd, wtext) == 0) logLastError("error setting control text in uiWindowsControlSetText()"); uiFree(wtext); } diff --git a/ui_windows.h b/ui_windows.h index d1a95786..6932ff4f 100644 --- a/ui_windows.h +++ b/ui_windows.h @@ -8,6 +8,7 @@ This file assumes that you have included and "ui.h" beforehand. It p #define __UI_UI_WINDOWS_H__ // uiWindowsNewControl() creates a new uiControl with the given Windows API control inside. +// You will need to provide the preferredSize() method yourself. typedef struct uiWindowsNewControlParams uiWindowsNewControlParams; struct uiWindowsNewControlParams { // These match the CreateWindowExW() function. @@ -21,25 +22,24 @@ struct uiWindowsNewControlParams { // ui redirects the message back and calls these functions. // Store the result in *lResult and return any non-FALSE value (such as TRUE) to return the given result; return FALSE to pass the notification up to your window procedure. // Note that these are only issued if they come from the uiControl itself; notifications from children of the uiControl (such as a header control) will be received normally. - BOOL (*onWM_COMMAND)(uiControl *c, WPARAM wParam, LPARAM lParam, void *data, LRESULT *lResult); - BOOL (*onWM_NOTIFY)(uiControl *c, WPARAM wParam, LPARAM lParam, void *data, LRESULT *lResult); + // TODO don't give WPARAM/LPARAM raw + BOOL (*onWM_COMMAND)(uiControl *c, WPARAM wParam, LPARAM lParam, LRESULT *lResult); + BOOL (*onWM_NOTIFY)(uiControl *c, WPARAM wParam, LPARAM lParam, LRESULT *lResult); // This is called in WM_DESTROY. - void (*onWM_DESTROY)(uiControl *c, void *data); - // This is the data parameter to all three of the above. - void *onCommandNotifyDestroyData; - - // This function is called when ui needs to know how to rearrange controls in a window. - // baseX and baseY are the base units used to convert between dialog units and pixels. - // internalLeading is the internal leading of the control font. - void (*preferredSize)(uiControl *c, int baseX, int baseY, LONG internalLeading, intmax_t *width, intmax_t *height); - - // Data you can get with uiWindowsControlData() - void *data; + void (*onWM_DESTROY)(uiControl *c); }; uiControl *uiWindowsNewControl(uiWindowsNewControlParams *); -void *uiWindowsControlData(uiControl *); -// use these in your preferredSize() implementation with baseX and baseY +// This contains the Windows-specific parts of the uiSizing structure. +// baseX and baseY are the dialog base units. +// internalLeading is the standard control font's internal leading; labels in uiForms use this for correct Y positioning. +struct uiSizingSys { + int baseX; + int baseY; + LONG internalLeading; +}; +// Use these in your preferredSize() implementation with baseX and baseY. +// TODO rename to DlgUnits? #define uiDlgUnitToX(dlg, baseX) MulDiv((dlg), baseX, 4) #define uiDlgUnitToY(dlg, baseY) MulDiv((dlg), baseY, 8) diff --git a/uipriv_windows.h b/uipriv_windows.h index 2c545eee..8e602882 100644 --- a/uipriv_windows.h +++ b/uipriv_windows.h @@ -54,12 +54,6 @@ extern WCHAR *windowText(HWND); // container_windows.c extern BOOL sharedWndProc(HWND, UINT, WPARAM, LPARAM, LRESULT *); -struct uiSizing { - uiSizingCommon - int baseX; - int baseY; - LONG internalLeading; -}; extern void resize(uiControl *, HWND, RECT, RECT); // comctl32_windows.c