From 5b36956ecbfa3a5fdcea13dc09c9ce33d00f0e6c Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Tue, 7 Apr 2015 04:02:21 -0400 Subject: [PATCH] Wrote up the initial uiButton implementation. It (mostly; just needs text and for that I need to add a uiControlHandle()) works! --- button_windows.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ newcontrol_windows.c | 8 +++++ test.c | 10 ++++++ ui.h | 7 ++++- ui_windows.h | 4 +++ window_windows.c | 6 ++++ 6 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 button_windows.c diff --git a/button_windows.c b/button_windows.c new file mode 100644 index 00000000..a66490d2 --- /dev/null +++ b/button_windows.c @@ -0,0 +1,73 @@ +// 7 april 2015 +#include "uipriv_windows.h" + +struct button { + uiControl *c; + void (*onClicked)(uiControl *, void *); + void *onClickedData; +}; + +#define B(x) ((struct button *) (x)) + +static BOOL onWM_COMMAND(uiControl *c, WPARAM wParam, LPARAM lParam, void *data, LRESULT *lResult) +{ + if (HIWORD(wParam) != BN_CLICKED) + return FALSE; + (*(B(data)->onClicked))(c, B(data)->onClickedData); + *lResult = 0; + return TRUE; +} + +static BOOL onWM_NOTIFY(uiControl *c, WPARAM wParam, LPARAM lParam, void *data, LRESULT *lResult) +{ + return FALSE; +} + +static void preferredSize(uiControl *c, int baseX, int baseY, LONG internalLeading, intmax_t *width, intmax_t *height) +{ + // TODO +} + +static void defaultOnClicked(uiControl *c, void *data) +{ + // do nothing +} + +uiControl *uiNewButton(const char *text) +{ + struct button *b; + uiWindowsNewControlParams p; + WCHAR *wtext; + + b = uiNew(struct button); + + p.dwExStyle = 0; + p.lpClassName = L"button"; + p.dwStyle = BS_PUSHBUTTON; + p.hInstance = hInstance; + p.onWM_COMMAND = onWM_COMMAND; + p.onWM_NOTIFY = onWM_NOTIFY; + p.onCommandNotifyData = b; + p.preferredSize = preferredSize; + p.data = b; + b->c = uiWindowsNewControl(&p); + + wtext = toUTF16(text); + // TODO set text + uiFree(wtext); + + b->onClicked = defaultOnClicked; + + return b->c; +} + +// TODO text + +void uiButtonOnClicked(uiControl *c, void (*f)(uiControl *, void *), void *data) +{ + struct button *b; + + b = (struct button *) uiWindowsControlData(c); + b->onClicked = f; + b->onClickedData = data; +} diff --git a/newcontrol_windows.c b/newcontrol_windows.c index f301a540..c26cbab9 100644 --- a/newcontrol_windows.c +++ b/newcontrol_windows.c @@ -10,6 +10,7 @@ struct uiSingleHWNDControl { BOOL (*onWM_NOTIFY)(uiControl *, WPARAM, LPARAM, void *, LRESULT *); void *onCommandNotifyData; void (*preferredSize)(uiControl *, int, int, LONG, intmax_t *, intmax_t *); + void *data; }; #define S(c) ((uiSingleHWNDControl *) (c)) @@ -100,8 +101,15 @@ uiControl *uiWindowsNewControl(uiWindowsNewControlParams *p) c->onCommandNotifyData = p->onCommandNotifyData; c->preferredSize = p->preferredSize; + c->data = p->data; + if ((*fv_SetWindowSubclass)(c->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; +} diff --git a/test.c b/test.c index 400c3f86..b2cb630d 100644 --- a/test.c +++ b/test.c @@ -9,10 +9,16 @@ int onClosing(uiWindow *w, void *data) return 1; } +void onClicked(uiControl *b, void *data) +{ + printf("button clicked!\n"); +} + int main(void) { uiInitError *err; uiWindow *w; + uiControl *button; err = uiInit(NULL); if (err != NULL) { @@ -25,6 +31,10 @@ int main(void) uiWindowOnClosing(w, onClosing, NULL); uiWindowShow(w); + button = uiNewButton("Click Me"); + uiButtonOnClicked(button, onClicked, NULL); + uiWindowSetChild(w, button); + uiMain(); printf("after uiMain()\n"); return 0; diff --git a/ui.h b/ui.h index ce0a44bf..cc10300a 100644 --- a/ui.h +++ b/ui.h @@ -15,6 +15,8 @@ void uiInitErrorFree(uiInitError *); void uiMain(void); void uiQuit(void); +typedef struct uiControl uiControl; + typedef struct uiWindow uiWindow; uiWindow *uiNewWindow(char *, int, int); void uiWindowDestroy(uiWindow *); @@ -23,7 +25,10 @@ uintptr_t uiWindowHandle(uiWindow *); void uiWindowShow(uiWindow *); void uiWindowHide(uiWindow *); void uiWindowOnClosing(uiWindow *, int (*)(uiWindow *, void *), void *); +void uiWindowSetChild(uiWindow *, uiControl *); -typedef struct uiControl uiControl; +uiControl *uiNewButton(const char *); +// TODO text +void uiButtonOnClicked(uiControl *, void (*)(uiControl *, void *), void *); #endif diff --git a/ui_windows.h b/ui_windows.h index 6186a619..22b0a141 100644 --- a/ui_windows.h +++ b/ui_windows.h @@ -30,8 +30,12 @@ struct uiWindowsNewControlParams { // 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; }; uiControl *uiWindowsNewControl(uiWindowsNewControlParams *); +void *uiWindowsControlData(uiControl *); // use these in your preferredSize() implementation with baseX and baseY #define uiDlgUnitToX(dlg, baseX) MulDiv((dlg), baseX, 4) diff --git a/window_windows.c b/window_windows.c index d5f675e2..3f2abb2f 100644 --- a/window_windows.c +++ b/window_windows.c @@ -133,3 +133,9 @@ void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data) w->onClosing = f; w->onClosingData = data; } + +void uiWindowSetChild(uiWindow *w, uiControl *c) +{ + w->child = c; + (*(w->child->setParent))(w->child, (uintptr_t) (w->hwnd)); +}