From 465d497cb6ec5388a67032d43a1327ab871e4857 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sun, 30 Aug 2015 12:25:53 -0400 Subject: [PATCH] Migrated all the single-HWND controls that don't have a child. Moment of truth time: do we require all controls to have a single HWND? Leaning toward yes. --- redo/windows/button.c | 2 +- redo/windows/checkbox.c | 108 ++++++++++++++++ {windows => redo/windows}/combobox.c | 36 +++--- {windows => redo/windows}/datetimepicker.c | 53 +++----- redo/windows/entry.c | 100 +++++++++++++++ {windows => redo/windows}/label.c | 42 +++---- {windows => redo/windows}/progressbar.c | 35 ++---- {windows => redo/windows}/separator.c | 27 ++-- redo/windows/slider.c | 80 ++++++++++++ windows/checkbox.c | 139 --------------------- windows/entry.c | 131 ------------------- windows/slider.c | 107 ---------------- 12 files changed, 360 insertions(+), 500 deletions(-) create mode 100644 redo/windows/checkbox.c rename {windows => redo/windows}/combobox.c (58%) rename {windows => redo/windows}/datetimepicker.c (78%) create mode 100644 redo/windows/entry.c rename {windows => redo/windows}/label.c (52%) rename {windows => redo/windows}/progressbar.c (59%) rename {windows => redo/windows}/separator.c (52%) create mode 100644 redo/windows/slider.c delete mode 100644 windows/checkbox.c delete mode 100644 windows/entry.c delete mode 100644 windows/slider.c diff --git a/redo/windows/button.c b/redo/windows/button.c index cca0ea4b..8c5aa952 100644 --- a/redo/windows/button.c +++ b/redo/windows/button.c @@ -8,7 +8,7 @@ struct uiButton { void *onClickedData; }; -uiDarwinDefineControlWithOnDestroy( +uiWindowsDefineControlWithOnDestroy( uiButton, // type name uiButtonType, // type function uiWindowsUnregisterWM_COMMANDHandler(this->hwnd); // on destroy diff --git a/redo/windows/checkbox.c b/redo/windows/checkbox.c new file mode 100644 index 00000000..d4df3ffb --- /dev/null +++ b/redo/windows/checkbox.c @@ -0,0 +1,108 @@ +// 7 april 2015 +#include "uipriv_windows.h" + +struct uiCheckbox { + uiWindowsControl c; + HWND hwnd; + void (*onToggled)(uiCheckbox *, void *); + void *onToggledData; +}; + +uiWindowsDefineControlWithOnDestroy( + uiCheckbox, // type name + uiCheckboxType, // type function + uiWindowsUnregisterWM_COMMANDHandler(this->hwnd); // on destroy +) + +static BOOL onWM_COMMAND(uiControl *cc, HWND hwnd, WORD code, LRESULT *lResult) +{ + uiCheckbox *c = uiCheckbox(cc); + WPARAM check; + + if (code != BN_CLICKED) + return FALSE; + + // we didn't use BS_AUTOCHECKBOX (TODO get link) so we have to manage the check state ourselves + check = BST_CHECKED; + if (SendMessage(c->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED) + check = BST_UNCHECKED; + SendMessage(c->hwnd, BM_SETCHECK, check, 0); + + (*(c->onToggled))(c, c->onToggledData); + *lResult = 0; + return TRUE; +} + +// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing +#define checkboxHeight 10 +// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx +#define checkboxXFromLeftOfBoxToLeftOfLabel 12 + +static void minimumSize(uiControl *cc, uiWindowsSizing *d, intmax_t *width, intmax_t *height) +{ + uiCheckbox *c = uiCheckbox(cc); + + *width = uiWindowsDlgUnitsToX(checkboxXFromLeftOfBoxToLeftOfLabel, d->BaseX) + uiWindowsWindowTextWidth(c->hwnd); + *height = uiWindowsDlgUnitsToY(checkboxHeight, d->BaseY); +} + +static void defaultOnToggled(uiCheckbox *c, void *data) +{ + // do nothing +} + +char *uiCheckboxText(uiCheckbox *c) +{ + return uiWindowsUtilText(c->hwnd); +} + +void uiCheckboxSetText(uiCheckbox *c, const char *text) +{ + uiWindowsUtilSetText(c->hwnd, text); + // changing the text might necessitate a change in the checkbox's size + uiControlQueueResize(uiControl(c)); +} + +void uiCheckboxOnToggled(uiCheckbox *c, void (*f)(uiCheckbox *, void *), void *data) +{ + c->onToggled = f; + c->onToggledData = data; +} + +int uiCheckboxChecked(uiCheckbox *c) +{ + return SendMessage(c->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED; +} + +void uiCheckboxSetChecked(uiCheckbox *c, int checked) +{ + WPARAM check; + + check = BST_CHECKED; + if (!checked) + check = BST_UNCHECKED; + SendMessage(c->hwnd, BM_SETCHECK, check, 0); +} + +uiCheckbox *uiNewCheckbox(const char *text) +{ + uiCheckbox *c; + WCHAR *wtext; + + c = (uiCheckbox *) uiNewControl(uiCheckboxType()); + + wtext = toUTF16(text); + c->hwnd = uiWindowsEnsureCreateControlHWND(0, + L"button", wtext, + BS_CHECKBOX | WS_TABSTOP, + hInstance, NULL, + TRUE); + uiFree(wtext); + + uiWindowsRegisterWM_COMMANDHandler(c->hwnd, onWM_COMMAND, uiControl(c)); + uiCheckboxOnToggled(c, defaultOnToggled, NULL); + + uiWindowsFinishNewControl(c, uiCheckbox); + + return c; +} diff --git a/windows/combobox.c b/redo/windows/combobox.c similarity index 58% rename from windows/combobox.c rename to redo/windows/combobox.c index c100c545..9d82b858 100644 --- a/windows/combobox.c +++ b/redo/windows/combobox.c @@ -3,33 +3,28 @@ // we as Common Controls 6 users don't need to worry about the height of comboboxes; see http://blogs.msdn.com/b/oldnewthing/archive/2006/03/10/548537.aspx -struct combobox { - uiCombobox c; +struct uiCombobox { + uiWindowsControl c; HWND hwnd; }; -uiDefineControlType(uiCombobox, uiTypeCombobox, struct combobox) - -static uintptr_t comboboxHandle(uiControl *cc) -{ - struct combobox *c = (struct combobox *) cc; - - return (uintptr_t) (c->hwnd); -} +uiWindowsDefineControl( + uiCombobox, // type name + uiComboboxType // type function +) // from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing #define comboboxWidth 107 /* this is actually the shorter progress bar width, but Microsoft only indicates as wide as necessary */ #define comboboxHeight 14 -static void comboboxPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) +static void minimumSize(uiControl *c, uiWindowsSizing *d, intmax_t *width, intmax_t *height) { - *width = uiWindowsDlgUnitsToX(comboboxWidth, d->Sys->BaseX); - *height = uiWindowsDlgUnitsToY(comboboxHeight, d->Sys->BaseY); + *width = uiWindowsDlgUnitsToX(comboboxWidth, d->BaseX); + *height = uiWindowsDlgUnitsToY(comboboxHeight, d->BaseY); } -static void comboboxAppend(uiCombobox *cc, const char *text) +void uiComboboxAppend(uiCombobox *c, const char *text) { - struct combobox *c = (struct combobox *) cc; WCHAR *wtext; LRESULT res; @@ -44,9 +39,9 @@ static void comboboxAppend(uiCombobox *cc, const char *text) static uiCombobox *finishNewCombobox(DWORD style) { - struct combobox *c; + uiCombobox *c; - c = (struct combobox *) uiWindowsNewSingleHWNDControl(uiTypeCombobox()); + c = (uiCombobox *) uiNewControl(uiComboboxType()); c->hwnd = uiWindowsUtilCreateControlHWND(WS_EX_CLIENTEDGE, L"combobox", L"", @@ -54,12 +49,9 @@ static uiCombobox *finishNewCombobox(DWORD style) hInstance, NULL, TRUE); - uiControl(c)->Handle = comboboxHandle; - uiControl(c)->PreferredSize = comboboxPreferredSize; + uiWindowsFinishNewControl(c, uiCombobox); - uiCombobox(c)->Append = comboboxAppend; - - return uiCombobox(c); + return c; } uiCombobox *uiNewCombobox(void) diff --git a/windows/datetimepicker.c b/redo/windows/datetimepicker.c similarity index 78% rename from windows/datetimepicker.c rename to redo/windows/datetimepicker.c index 63c373c3..9cf7d9b8 100644 --- a/windows/datetimepicker.c +++ b/redo/windows/datetimepicker.c @@ -1,13 +1,16 @@ // 22 may 2015 #include "uipriv_windows.h" -struct datetimepicker { - uiDateTimePicker d; +struct uiDateTimePicker { + uiWindowsControl c; HWND hwnd; - void (*baseCommitDestroy)(uiControl *); }; -uiDefineControlType(uiDateTimePicker, uiTypeDateTimePicker, struct datetimepicker) +uiWindowsDefineControlWithOnDestroy( + uiDateTimePicker, // type name + uiDateTimePickerType, // type function + uiWindowsUnregisterReceiveWM_WININICHANGE(this->hwnd); // on destroy +) // utility functions @@ -103,42 +106,27 @@ static void setDateTimeFormat(HWND hwnd) // control implementation -static void datetimepickerCommitDestroy(uiControl *c) -{ - struct datetimepicker *d = (struct datetimepicker *) c; - - uiWindowsUnregisterReceiveWM_WININICHANGE(d->hwnd); - (*(d->baseCommitDestroy))(uiControl(d)); -} - -static uintptr_t datetimepickerHandle(uiControl *c) -{ - struct datetimepicker *d = (struct datetimepicker *) c; - - return (uintptr_t) (d->hwnd); -} - // the height returned from DTM_GETIDEALSIZE is unreliable; see http://stackoverflow.com/questions/30626549/what-is-the-proper-use-of-dtm-getidealsize-treating-the-returned-size-as-pixels // from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing #define entryHeight 14 -static void datetimepickerPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) +static void minimumSize(uiControl *c, uiWindowsSizing *d, intmax_t *width, intmax_t *height) { - struct datetimepicker *dd = (struct datetimepicker *) c; + uiDateTimePicker *d = uiDateTimePicker(c); SIZE s; s.cx = 0; s.cy = 0; SendMessageW(dd->hwnd, DTM_GETIDEALSIZE, 0, (LPARAM) (&s)); *width = s.cx; - *height = uiWindowsDlgUnitsToY(entryHeight, d->Sys->BaseY); + *height = uiWindowsDlgUnitsToY(entryHeight, d->BaseY); } -uiDateTimePicker *finishNewDateTimePicker(DWORD style) +static uiDateTimePicker *finishNewDateTimePicker(DWORD style) { - struct datetimepicker *d; + uiDateTimePicker *d; - d = (struct datetimepicker *) uiWindowsNewSingleHWNDControl(uiTypeDateTimePicker()); + d = (uiDateTimePicker *) uiNewControl(uiDateTimePickerType()); d->hwnd = uiWindowsUtilCreateControlHWND(WS_EX_CLIENTEDGE, DATETIMEPICK_CLASSW, L"", @@ -151,12 +139,9 @@ uiDateTimePicker *finishNewDateTimePicker(DWORD style) // for our date/time mode, we do it in a subclass assigned in uiNewDateTimePicker() uiWindowsRegisterReceiveWM_WININICHANGE(d->hwnd); - d->baseCommitDestroy = uiControl(d)->CommitDestroy; - uiControl(d)->CommitDestroy = datetimepickerCommitDestroy; - uiControl(d)->Handle = datetimepickerHandle; - uiControl(d)->PreferredSize = datetimepickerPreferredSize; + uiWindowsFinishNewControl(d, uiDateTimePicker); - return uiDateTimePicker(d); + return d; } static LRESULT CALLBACK datetimepickerSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) @@ -178,15 +163,13 @@ static LRESULT CALLBACK datetimepickerSubProc(HWND hwnd, UINT uMsg, WPARAM wPara uiDateTimePicker *uiNewDateTimePicker(void) { - uiDateTimePicker *dtp; - struct datetimepicker *d; + uiDateTimePicker *d; - dtp = finishNewDateTimePicker(0); - d = (struct datetimepicker *) dtp; + d = finishNewDateTimePicker(0); setDateTimeFormat(d->hwnd); if (SetWindowSubclass(d->hwnd, datetimepickerSubProc, 0, (DWORD_PTR) d) == FALSE) logLastError("error subclassing date-time-picker to assist in locale change handling in uiNewDateTimePicker()"); - return dtp; + return d; } uiDateTimePicker *uiNewDatePicker(void) diff --git a/redo/windows/entry.c b/redo/windows/entry.c new file mode 100644 index 00000000..9ccebe41 --- /dev/null +++ b/redo/windows/entry.c @@ -0,0 +1,100 @@ +// 8 april 2015 +#include "uipriv_windows.h" + +struct uiEntry { + uiWindowsControl c; + HWND hwnd; + void (*onChanged)(uiEntry *, void *); + void *onChangedData; + BOOL inhibitChanged; +}; + +uiWindowsDefineControlWithOnDestroy( + uiEntry, // type name + uiEntryType, // type function + uiWindowsUnregisterWM_COMMANDHandler(this->hwnd); // on destroy +) + +static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) +{ + uiEntry *e = uiEntry(c); + + if (code != EN_CHANGE) + return FALSE; + if (e->inhibitChanged) + return FALSE; + (*(e->onChanged))(e, e->onChangedData); + *lResult = 0; + return TRUE; +} + +// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing +#define entryWidth 107 /* this is actually the shorter progress bar width, but Microsoft only indicates as wide as necessary */ +#define entryHeight 14 + +static void minimumSize(uiControl *c, uiWindowsSizing *d, intmax_t *width, intmax_t *height) +{ + *width = uiWindowsDlgUnitsToX(entryWidth, d->BaseX); + *height = uiWindowsDlgUnitsToY(entryHeight, d->BaseY); +} + +static void defaultOnChanged(uiEntry *e, void *data) +{ + // do nothing +} + +char *uiEntryText(uiEntry *e) +{ + return uiWindowsUtilText(e->hwnd); +} + +void uiEntrySetText(uiEntry *e, const char *text) +{ + // doing this raises an EN_CHANGED + e->inhibitChanged = TRUE; + uiWindowsUtilSetText(e->hwnd, text); + e->inhibitChanged = FALSE; + // don't queue the control for resize; entry sizes are independent of their contents +} + +void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *, void *), void *data) +{ + e->onChanged = f; + e->onChangedData = data; +} + +int uiEntryReadOnly(uiEntry *e) +{ + return (getStyle(e->hwnd) & ES_READONLY) != 0; +} + +void uiEntrySetReadOnly(uiEntry *e, int readonly) +{ + WPARAM ro; + + ro = (WPARAM) FALSE; + if (readonly) + ro = (WPARAM) TRUE; + if (SendMessage(e->hwnd, EM_SETREADONLY, ro, 0) == 0) + logLastError("error making uiEntry read-only in uiEntrySetReadOnly()"); +} + +uiEntry *uiNewEntry(void) +{ + uiEntry *e; + + e = (uiEntry *) uiWindowsNewSingleHWNDControl(uiNewControl()); + + e->hwnd = uiWindowsUtilCreateControlHWND(WS_EX_CLIENTEDGE, + L"edit", L"", + ES_AUTOHSCROLL | ES_LEFT | ES_NOHIDESEL | WS_TABSTOP, + hInstance, NULL, + TRUE); + + uiWindowsRegisterWM_COMMANDHandler(e->hwnd, onWM_COMMAND, uiControl(e)); + uiEntrySetOnChanged(e, defaultOnChanged, NULL); + + uiWindowsFinishNewControl(e, uiEntry); + + return e; +} diff --git a/windows/label.c b/redo/windows/label.c similarity index 52% rename from windows/label.c rename to redo/windows/label.c index 27180fce..17e9c70a 100644 --- a/windows/label.c +++ b/redo/windows/label.c @@ -1,42 +1,34 @@ // 11 april 2015 #include "uipriv_windows.h" -struct label { - uiLabel l; +struct uiLabel { + uiWindowsControl c; HWND hwnd; }; -uiDefineControlType(uiLabel, uiTypeLabel, struct label) - -static uintptr_t labelHandle(uiControl *c) -{ - struct label *l = (struct label *) c; - - return (uintptr_t) (l->hwnd); -} +uiWindowsDefineControl( + uiLabel, // type name + uiLabelType // type function +) // via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing #define labelHeight 8 -static void labelPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) +static void minimumSize(uiControl *c, uiWindowsSizing *d, intmax_t *width, intmax_t *height) { - struct label *l = (struct label *) c; + uiLabel *l = uiLabel(c); *width = uiWindowsWindowTextWidth(l->hwnd); - *height = uiWindowsDlgUnitsToY(labelHeight, d->Sys->BaseY); + *height = uiWindowsDlgUnitsToY(labelHeight, d->BaseY); } -static char *labelText(uiLabel *ll) +char *uiLabelText(uiLabel *l) { - struct label *l = (struct label *) ll; - return uiWindowsUtilText(l->hwnd); } -static void labelSetText(uiLabel *ll, const char *text) +void uiLabelSetText(uiLabel *l, const char *text) { - struct label *l = (struct label *) ll; - uiWindowsUtilSetText(l->hwnd, text); // changing the text might necessitate a change in the label's size uiControlQueueResize(uiControl(l)); @@ -44,10 +36,10 @@ static void labelSetText(uiLabel *ll, const char *text) uiLabel *uiNewLabel(const char *text) { - struct label *l; + uiLabel *l; WCHAR *wtext; - l = (struct label *) uiWindowsNewSingleHWNDControl(uiTypeLabel()); + l = (uiLabel *) uiNewControl(uiLabelType()); wtext = toUTF16(text); l->hwnd = uiWindowsUtilCreateControlHWND(0, @@ -59,11 +51,7 @@ uiLabel *uiNewLabel(const char *text) TRUE); uiFree(wtext); - uiControl(l)->Handle = labelHandle; - uiControl(l)->PreferredSize = labelPreferredSize; + uiWindowsFinishNewControl(l, uiLabel); - uiLabel(l)->Text = labelText; - uiLabel(l)->SetText = labelSetText; - - return uiLabel(l); + return l; } diff --git a/windows/progressbar.c b/redo/windows/progressbar.c similarity index 59% rename from windows/progressbar.c rename to redo/windows/progressbar.c index 00706535..983e2030 100644 --- a/windows/progressbar.c +++ b/redo/windows/progressbar.c @@ -1,25 +1,21 @@ // 19 may 2015 #include "uipriv_windows.h" -struct progressbar { - uiProgressBar p; +struct uiProgressBar { + uiWindowsControl c; HWND hwnd; }; -uiDefineControlType(uiProgressBar, uiTypeProgressBar, struct progressbar) - -static uintptr_t progressbarHandle(uiControl *c) -{ - struct progressbar *p = (struct progressbar *) c; - - return (uintptr_t) (p->hwnd); -} +uiWindowsDefineControl( + uiProgressBar, // type name + uiProgressBarType // type function +) // via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing #define pbarWidth 237 #define pbarHeight 8 -static void progressbarPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) +static void minimumSize(uiControl *c, uiWindowsSizing *d, intmax_t *width, intmax_t *height) { *width = uiWindowsDlgUnitsToX(pbarWidth, d->Sys->BaseX); *height = uiWindowsDlgUnitsToY(pbarHeight, d->Sys->BaseY); @@ -29,12 +25,10 @@ static void progressbarPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, // we have to set the progress bar to value + 1 and decrease it back to value if we want an "instant" change // see http://stackoverflow.com/questions/2217688/windows-7-aero-theme-progress-bar-bug // it's not ideal/perfect, but it will have to do -static void progressbarSetValue(uiProgressBar *pp, int value) +void uiProgressBarSetValue(uiProgressBar *p, int value) { - struct progressbar *p = (struct progressbar *) pp; - if (value < 0 || value > 100) - complain("value %d out of range in progressbarSetValue()", value); + complain("value %d out of range in uiProgressBarSetValue()", value); if (value == 100) { // because we can't 101 SendMessageW(p->hwnd, PBM_SETRANGE32, 0, 101); SendMessageW(p->hwnd, PBM_SETPOS, 101, 0); @@ -48,9 +42,9 @@ static void progressbarSetValue(uiProgressBar *pp, int value) uiProgressBar *uiNewProgressBar(void) { - struct progressbar *p; + uiProgressBar *p; - p = (struct progressbar *) uiWindowsNewSingleHWNDControl(uiTypeProgressBar()); + p = (uiProgressBar *) uiNewControl(uiProgressBarType()); p->hwnd = uiWindowsUtilCreateControlHWND(0, PROGRESS_CLASSW, L"", @@ -58,10 +52,7 @@ uiProgressBar *uiNewProgressBar(void) hInstance, NULL, FALSE); - uiControl(p)->Handle = progressbarHandle; - uiControl(p)->PreferredSize = progressbarPreferredSize; + uiWindowsFinishNewControl(p, uiProgressBar); - uiProgressBar(p)->SetValue = progressbarSetValue; - - return uiProgressBar(p); + return p; } diff --git a/windows/separator.c b/redo/windows/separator.c similarity index 52% rename from windows/separator.c rename to redo/windows/separator.c index a28b7f58..771201f6 100644 --- a/windows/separator.c +++ b/redo/windows/separator.c @@ -5,24 +5,20 @@ // - http://stackoverflow.com/questions/2892703/how-do-i-draw-separators // - https://msdn.microsoft.com/en-us/library/windows/desktop/dn742405%28v=vs.85%29.aspx -struct separator { - uiSeparator s; +struct uiSeparator { + uiWindowsControl c; HWND hwnd; }; -uiDefineControlType(uiSeparator, uiTypeSeparator, struct separator) - -static uintptr_t separatorHandle(uiControl *c) -{ - struct separator *s = (struct separator *) c; - - return (uintptr_t) (s->hwnd); -} +uiWindowsDefineControl( + uiSeparator, // type name + uiSeparatorType // type function +) // via https://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx #define separatorHeight 1 -static void separatorPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) +static void minimumSize(uiControl *c, uiWindowsSizing *d, intmax_t *width, intmax_t *height) { *width = 1; // TODO *height = uiWindowsDlgUnitsToY(separatorHeight, d->Sys->BaseY); @@ -30,9 +26,9 @@ static void separatorPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, i uiSeparator *uiNewHorizontalSeparator(void) { - struct separator *s; + uiSeparator *s; - s = (struct separator *) uiWindowsNewSingleHWNDControl(uiTypeSeparator()); + s = (uiSeparator *) uiNewControl(uiSeparatorType()); s->hwnd = uiWindowsUtilCreateControlHWND(0, L"static", L"", @@ -40,8 +36,7 @@ uiSeparator *uiNewHorizontalSeparator(void) hInstance, NULL, TRUE); - uiControl(s)->Handle = separatorHandle; - uiControl(s)->PreferredSize = separatorPreferredSize; + uiWindowsFinishNewControl(s, uiSeparator); - return uiSeparator(s); + return s; } diff --git a/redo/windows/slider.c b/redo/windows/slider.c new file mode 100644 index 00000000..299bd9a1 --- /dev/null +++ b/redo/windows/slider.c @@ -0,0 +1,80 @@ +// 20 may 2015 +#include "uipriv_windows.h" + +struct uiSlider { + uiWindowsControl c; + HWND hwnd; + void (*onChanged)(uiSlider *, void *); + void *onChangedData; +}; + +uiWindowsDefineControlWithOnDestroy( + uiSlider, // type name + uiSliderType, // type function + uiWindowsUnregisterWM_HSCROLLHandler(this->hwnd); // on destroy +) + +static BOOL onWM_HSCROLL(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) +{ + uiSlider *s = uiSlider(c); + + (*(s->onChanged))(s, s->onChangedData); + *lResult = 0; + return TRUE; +} + +// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing +#define sliderWidth 107 /* this is actually the shorter progress bar width, but Microsoft doesn't indicate a width */ +#define sliderHeight 15 + +static void minimumSize(uiControl *c, uiWindowsSizing *d, intmax_t *width, intmax_t *height) +{ + *width = uiWindowsDlgUnitsToX(sliderWidth, d->BaseX); + *height = uiWindowsDlgUnitsToY(sliderHeight, d->BaseY); +} + +static void defaultOnChanged(uiSlider *s, void *data) +{ + // do nothing +} + +intmax_t uiSliderValue(uiSlider *s) +{ + return (intmax_t) SendMessageW(s->hwnd, TBM_GETPOS, 0, 0); +} + +void uiSliderSetValue(uiSlider *s, intmax_t value) +{ + // don't use TBM_SETPOSNOTIFY; that triggers an event + SendMessageW(s->hwnd, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) value); +} + +void uiSliderOnChanged(uiSlider *s, void (*f)(uiSlider *, void *), void *data) +{ + s->onChanged = f; + s->onChangedData = data; +} + +uiSlider *uiNewSlider(intmax_t min, intmax_t max) +{ + uiSlider *s; + + s = (uiSlider *) uiNewControl(uiSliderType()); + + s->hwnd = uiWindowsUtilCreateControlHWND(0, + TRACKBAR_CLASSW, L"", + TBS_HORZ | TBS_TOOLTIPS | TBS_TRANSPARENTBKGND | WS_TABSTOP, + hInstance, NULL, + TRUE); + + uiWindowsRegisterWM_HSCROLLHandler(s->hwnd, onWM_HSCROLL, uiControl(s)); + uiSliderOnChanged(s, defaultOnChanged, NULL); + + SendMessageW(s->hwnd, TBM_SETRANGEMIN, (WPARAM) TRUE, (LPARAM) min); + SendMessageW(s->hwnd, TBM_SETRANGEMAX, (WPARAM) TRUE, (LPARAM) max); + SendMessageW(s->hwnd, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) min); + + uiWindowsFinishNewControl(s, uiSlider); + + return s; +} diff --git a/windows/checkbox.c b/windows/checkbox.c deleted file mode 100644 index d73b42f9..00000000 --- a/windows/checkbox.c +++ /dev/null @@ -1,139 +0,0 @@ -// 7 april 2015 -#include "uipriv_windows.h" - -struct checkbox { - uiCheckbox c; - HWND hwnd; - void (*onToggled)(uiCheckbox *, void *); - void *onToggledData; - void (*baseCommitDestroy)(uiControl *); -}; - -uiDefineControlType(uiCheckbox, uiTypeCheckbox, struct checkbox) - -static BOOL onWM_COMMAND(uiControl *cc, HWND hwnd, WORD code, LRESULT *lResult) -{ - struct checkbox *c = (struct checkbox *) cc; - WPARAM check; - - if (code != BN_CLICKED) - return FALSE; - - // we didn't use BS_AUTOCHECKBOX (see controls_windows.go) so we have to manage the check state ourselves - check = BST_CHECKED; - if (SendMessage(c->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED) - check = BST_UNCHECKED; - SendMessage(c->hwnd, BM_SETCHECK, check, 0); - - (*(c->onToggled))(uiCheckbox(c), c->onToggledData); - *lResult = 0; - return TRUE; -} - -static void checkboxCommitDestroy(uiControl *cc) -{ - struct checkbox *c = (struct checkbox *) cc; - - uiWindowsUnregisterWM_COMMANDHandler(c->hwnd); - (*(c->baseCommitDestroy))(uiControl(c)); -} - -static uintptr_t checkboxHandle(uiControl *cc) -{ - struct checkbox *c = (struct checkbox *) cc; - - return (uintptr_t) (c->hwnd); -} - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define checkboxHeight 10 -// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx -#define checkboxXFromLeftOfBoxToLeftOfLabel 12 - -static void checkboxPreferredSize(uiControl *cc, uiSizing *d, intmax_t *width, intmax_t *height) -{ - struct checkbox *c = (struct checkbox *) cc; - - *width = uiWindowsDlgUnitsToX(checkboxXFromLeftOfBoxToLeftOfLabel, d->Sys->BaseX) + uiWindowsWindowTextWidth(c->hwnd); - *height = uiWindowsDlgUnitsToY(checkboxHeight, d->Sys->BaseY); -} - -static void defaultOnToggled(uiCheckbox *c, void *data) -{ - // do nothing -} - -static char *checkboxText(uiCheckbox *cc) -{ - struct checkbox *c = (struct checkbox *) cc; - - return uiWindowsUtilText(c->hwnd); -} - -static void checkboxSetText(uiCheckbox *cc, const char *text) -{ - struct checkbox *c = (struct checkbox *) cc; - - uiWindowsUtilSetText(c->hwnd, text); - // changing the text might necessitate a change in the checkbox's size - uiControlQueueResize(uiControl(c)); -} - -static void checkboxOnToggled(uiCheckbox *cc, void (*f)(uiCheckbox *, void *), void *data) -{ - struct checkbox *c = (struct checkbox *) cc; - - c->onToggled = f; - c->onToggledData = data; -} - -static int checkboxChecked(uiCheckbox *cc) -{ - struct checkbox *c = (struct checkbox *) cc; - - return SendMessage(c->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED; -} - -static void checkboxSetChecked(uiCheckbox *cc, int checked) -{ - struct checkbox *c = (struct checkbox *) cc; - WPARAM check; - - check = BST_CHECKED; - if (!checked) - check = BST_UNCHECKED; - SendMessage(c->hwnd, BM_SETCHECK, check, 0); -} - -uiCheckbox *uiNewCheckbox(const char *text) -{ - struct checkbox *c; - WCHAR *wtext; - - c = (struct checkbox *) uiWindowsNewSingleHWNDControl(uiTypeCheckbox()); - - wtext = toUTF16(text); - c->hwnd = uiWindowsUtilCreateControlHWND(0, - L"button", wtext, - BS_CHECKBOX | WS_TABSTOP, - hInstance, NULL, - TRUE); - uiFree(wtext); - - uiWindowsRegisterWM_COMMANDHandler(c->hwnd, onWM_COMMAND, uiControl(c)); - - c->onToggled = defaultOnToggled; - - uiControl(c)->Handle = checkboxHandle; - uiControl(c)->PreferredSize = checkboxPreferredSize; - c->baseCommitDestroy = uiControl(c)->CommitDestroy; - uiControl(c)->CommitDestroy = checkboxCommitDestroy; - - uiCheckbox(c)->Text = checkboxText; - uiCheckbox(c)->SetText = checkboxSetText; - uiCheckbox(c)->OnToggled = checkboxOnToggled; - uiCheckbox(c)->Checked = checkboxChecked; - uiCheckbox(c)->SetChecked = checkboxSetChecked; - - return uiCheckbox(c); -} diff --git a/windows/entry.c b/windows/entry.c deleted file mode 100644 index 3260a519..00000000 --- a/windows/entry.c +++ /dev/null @@ -1,131 +0,0 @@ -// 8 april 2015 -#include "uipriv_windows.h" - -struct entry { - uiEntry e; - HWND hwnd; - void (*onChanged)(uiEntry *, void *); - void *onChangedData; - BOOL inhibitChanged; - void (*baseCommitDestroy)(uiControl *); -}; - -uiDefineControlType(uiEntry, uiTypeEntry, struct entry) - -static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) -{ - struct entry *e = (struct entry *) c; - - if (code != EN_CHANGE) - return FALSE; - if (e->inhibitChanged) - return FALSE; - (*(e->onChanged))(uiEntry(e), e->onChangedData); - *lResult = 0; - return TRUE; -} - -static void entryCommitDestroy(uiControl *c) -{ - struct entry *e = (struct entry *) c; - - uiWindowsUnregisterWM_COMMANDHandler(e->hwnd); - (*(e->baseCommitDestroy))(uiControl(e)); -} - -static uintptr_t entryHandle(uiControl *c) -{ - struct entry *e = (struct entry *) c; - - return (uintptr_t) (e->hwnd); -} - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define entryWidth 107 /* this is actually the shorter progress bar width, but Microsoft only indicates as wide as necessary */ -#define entryHeight 14 - -static void entryPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) -{ - *width = uiWindowsDlgUnitsToX(entryWidth, d->Sys->BaseX); - *height = uiWindowsDlgUnitsToY(entryHeight, d->Sys->BaseY); -} - -static void defaultOnChanged(uiEntry *e, void *data) -{ - // do nothing -} - -static char *entryText(uiEntry *ee) -{ - struct entry *e = (struct entry *) ee; - - return uiWindowsUtilText(e->hwnd); -} - -static void entrySetText(uiEntry *ee, const char *text) -{ - struct entry *e = (struct entry *) ee; - - // doing this raises an EN_CHANGED - e->inhibitChanged = TRUE; - uiWindowsUtilSetText(e->hwnd, text); - e->inhibitChanged = FALSE; - // don't queue the control for resize; entry sizes are independent of their contents -} - -static void entryOnChanged(uiEntry *ee, void (*f)(uiEntry *, void *), void *data) -{ - struct entry *e = (struct entry *) ee; - - e->onChanged = f; - e->onChangedData = data; -} - -static int entryReadOnly(uiEntry *ee) -{ - struct entry *e = (struct entry *) ee; - - return (getStyle(e->hwnd) & ES_READONLY) != 0; -} - -static void entrySetReadOnly(uiEntry *ee, int readonly) -{ - struct entry *e = (struct entry *) ee; - WPARAM ro; - - ro = (WPARAM) FALSE; - if (readonly) - ro = (WPARAM) TRUE; - if (SendMessage(e->hwnd, EM_SETREADONLY, ro, 0) == 0) - logLastError("error making uiEntry read-only in entrySetReadOnly()"); -} - -uiEntry *uiNewEntry(void) -{ - struct entry *e; - - e = (struct entry *) uiWindowsNewSingleHWNDControl(uiTypeEntry()); - - e->hwnd = uiWindowsUtilCreateControlHWND(WS_EX_CLIENTEDGE, - L"edit", L"", - ES_AUTOHSCROLL | ES_LEFT | ES_NOHIDESEL | WS_TABSTOP, - hInstance, NULL, - TRUE); - - uiWindowsRegisterWM_COMMANDHandler(e->hwnd, onWM_COMMAND, uiControl(e)); - - e->onChanged = defaultOnChanged; - - uiControl(e)->Handle = entryHandle; - uiControl(e)->PreferredSize = entryPreferredSize; - e->baseCommitDestroy = uiControl(e)->CommitDestroy; - uiControl(e)->CommitDestroy = entryCommitDestroy; - - uiEntry(e)->Text = entryText; - uiEntry(e)->SetText = entrySetText; - uiEntry(e)->OnChanged = entryOnChanged; - uiEntry(e)->ReadOnly = entryReadOnly; - uiEntry(e)->SetReadOnly = entrySetReadOnly; - - return uiEntry(e); -} diff --git a/windows/slider.c b/windows/slider.c deleted file mode 100644 index 0c8ea53d..00000000 --- a/windows/slider.c +++ /dev/null @@ -1,107 +0,0 @@ -// 20 may 2015 -#include "uipriv_windows.h" - -struct slider { - uiSlider s; - HWND hwnd; - void (*baseResize)(uiControl *, intmax_t, intmax_t, intmax_t, intmax_t, uiSizing *); - void (*onChanged)(uiSlider *, void *); - void *onChangedData; - void (*baseCommitDestroy)(uiControl *); -}; - -uiDefineControlType(uiSlider, uiTypeSlider, struct slider) - -static BOOL onWM_HSCROLL(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) -{ - struct slider *s = (struct slider *) c; - - (*(s->onChanged))(uiSlider(s), s->onChangedData); - *lResult = 0; - return TRUE; -} - -static void sliderCommitDestroy(uiControl *c) -{ - struct slider *s = (struct slider *) c; - - uiWindowsUnregisterWM_HSCROLLHandler(s->hwnd); - (*(s->baseCommitDestroy))(uiControl(s)); -} - -static uintptr_t sliderHandle(uiControl *c) -{ - struct slider *s = (struct slider *) c; - - return (uintptr_t) (s->hwnd); -} - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define sliderWidth 107 /* this is actually the shorter progress bar width, but Microsoft doesn't indicate a width */ -#define sliderHeight 15 - -static void sliderPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) -{ - *width = uiWindowsDlgUnitsToX(sliderWidth, d->Sys->BaseX); - *height = uiWindowsDlgUnitsToY(sliderHeight, d->Sys->BaseY); -} - -static void defaultOnChanged(uiSlider *s, void *data) -{ - // do nothing -} - -static intmax_t sliderValue(uiSlider *ss) -{ - struct slider *s = (struct slider *) ss; - - return (intmax_t) SendMessageW(s->hwnd, TBM_GETPOS, 0, 0); -} - -static void sliderSetValue(uiSlider *ss, intmax_t value) -{ - struct slider *s = (struct slider *) ss; - - // don't use TBM_SETPOSNOTIFY; that triggers an event - SendMessageW(s->hwnd, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) value); -} - -static void sliderOnChanged(uiSlider *ss, void (*f)(uiSlider *, void *), void *data) -{ - struct slider *s = (struct slider *) ss; - - s->onChanged = f; - s->onChangedData = data; -} - -uiSlider *uiNewSlider(intmax_t min, intmax_t max) -{ - struct slider *s; - - s = (struct slider *) uiWindowsNewSingleHWNDControl(uiTypeSlider()); - - s->hwnd = uiWindowsUtilCreateControlHWND(0, - TRACKBAR_CLASSW, L"", - TBS_HORZ | TBS_TOOLTIPS | TBS_TRANSPARENTBKGND | WS_TABSTOP, - hInstance, NULL, - TRUE); - - uiWindowsRegisterWM_HSCROLLHandler(s->hwnd, onWM_HSCROLL, uiControl(s)); - - SendMessageW(s->hwnd, TBM_SETRANGEMIN, (WPARAM) TRUE, (LPARAM) min); - SendMessageW(s->hwnd, TBM_SETRANGEMAX, (WPARAM) TRUE, (LPARAM) max); - SendMessageW(s->hwnd, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) min); - - s->onChanged = defaultOnChanged; - - uiControl(s)->Handle = sliderHandle; - uiControl(s)->PreferredSize = sliderPreferredSize; - s->baseCommitDestroy = uiControl(s)->CommitDestroy; - uiControl(s)->CommitDestroy = sliderCommitDestroy; - - uiSlider(s)->Value = sliderValue; - uiSlider(s)->SetValue = sliderSetValue; - uiSlider(s)->OnChanged = sliderOnChanged; - - return uiSlider(s); -}