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.
This commit is contained in:
parent
d4bb41f4c0
commit
465d497cb6
|
@ -8,7 +8,7 @@ struct uiButton {
|
||||||
void *onClickedData;
|
void *onClickedData;
|
||||||
};
|
};
|
||||||
|
|
||||||
uiDarwinDefineControlWithOnDestroy(
|
uiWindowsDefineControlWithOnDestroy(
|
||||||
uiButton, // type name
|
uiButton, // type name
|
||||||
uiButtonType, // type function
|
uiButtonType, // type function
|
||||||
uiWindowsUnregisterWM_COMMANDHandler(this->hwnd); // on destroy
|
uiWindowsUnregisterWM_COMMANDHandler(this->hwnd); // on destroy
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
// 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 {
|
struct uiCombobox {
|
||||||
uiCombobox c;
|
uiWindowsControl c;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
uiDefineControlType(uiCombobox, uiTypeCombobox, struct combobox)
|
uiWindowsDefineControl(
|
||||||
|
uiCombobox, // type name
|
||||||
static uintptr_t comboboxHandle(uiControl *cc)
|
uiComboboxType // type function
|
||||||
{
|
)
|
||||||
struct combobox *c = (struct combobox *) cc;
|
|
||||||
|
|
||||||
return (uintptr_t) (c->hwnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
|
// 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 comboboxWidth 107 /* this is actually the shorter progress bar width, but Microsoft only indicates as wide as necessary */
|
||||||
#define comboboxHeight 14
|
#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);
|
*width = uiWindowsDlgUnitsToX(comboboxWidth, d->BaseX);
|
||||||
*height = uiWindowsDlgUnitsToY(comboboxHeight, d->Sys->BaseY);
|
*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;
|
WCHAR *wtext;
|
||||||
LRESULT res;
|
LRESULT res;
|
||||||
|
|
||||||
|
@ -44,9 +39,9 @@ static void comboboxAppend(uiCombobox *cc, const char *text)
|
||||||
|
|
||||||
static uiCombobox *finishNewCombobox(DWORD style)
|
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,
|
c->hwnd = uiWindowsUtilCreateControlHWND(WS_EX_CLIENTEDGE,
|
||||||
L"combobox", L"",
|
L"combobox", L"",
|
||||||
|
@ -54,12 +49,9 @@ static uiCombobox *finishNewCombobox(DWORD style)
|
||||||
hInstance, NULL,
|
hInstance, NULL,
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
uiControl(c)->Handle = comboboxHandle;
|
uiWindowsFinishNewControl(c, uiCombobox);
|
||||||
uiControl(c)->PreferredSize = comboboxPreferredSize;
|
|
||||||
|
|
||||||
uiCombobox(c)->Append = comboboxAppend;
|
return c;
|
||||||
|
|
||||||
return uiCombobox(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uiCombobox *uiNewCombobox(void)
|
uiCombobox *uiNewCombobox(void)
|
|
@ -1,13 +1,16 @@
|
||||||
// 22 may 2015
|
// 22 may 2015
|
||||||
#include "uipriv_windows.h"
|
#include "uipriv_windows.h"
|
||||||
|
|
||||||
struct datetimepicker {
|
struct uiDateTimePicker {
|
||||||
uiDateTimePicker d;
|
uiWindowsControl c;
|
||||||
HWND hwnd;
|
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
|
// utility functions
|
||||||
|
|
||||||
|
@ -103,42 +106,27 @@ static void setDateTimeFormat(HWND hwnd)
|
||||||
|
|
||||||
// control implementation
|
// 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
|
// 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
|
// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
|
||||||
#define entryHeight 14
|
#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;
|
SIZE s;
|
||||||
|
|
||||||
s.cx = 0;
|
s.cx = 0;
|
||||||
s.cy = 0;
|
s.cy = 0;
|
||||||
SendMessageW(dd->hwnd, DTM_GETIDEALSIZE, 0, (LPARAM) (&s));
|
SendMessageW(dd->hwnd, DTM_GETIDEALSIZE, 0, (LPARAM) (&s));
|
||||||
*width = s.cx;
|
*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,
|
d->hwnd = uiWindowsUtilCreateControlHWND(WS_EX_CLIENTEDGE,
|
||||||
DATETIMEPICK_CLASSW, L"",
|
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()
|
// for our date/time mode, we do it in a subclass assigned in uiNewDateTimePicker()
|
||||||
uiWindowsRegisterReceiveWM_WININICHANGE(d->hwnd);
|
uiWindowsRegisterReceiveWM_WININICHANGE(d->hwnd);
|
||||||
|
|
||||||
d->baseCommitDestroy = uiControl(d)->CommitDestroy;
|
uiWindowsFinishNewControl(d, uiDateTimePicker);
|
||||||
uiControl(d)->CommitDestroy = datetimepickerCommitDestroy;
|
|
||||||
uiControl(d)->Handle = datetimepickerHandle;
|
|
||||||
uiControl(d)->PreferredSize = datetimepickerPreferredSize;
|
|
||||||
|
|
||||||
return uiDateTimePicker(d);
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LRESULT CALLBACK datetimepickerSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
|
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 *uiNewDateTimePicker(void)
|
||||||
{
|
{
|
||||||
uiDateTimePicker *dtp;
|
uiDateTimePicker *d;
|
||||||
struct datetimepicker *d;
|
|
||||||
|
|
||||||
dtp = finishNewDateTimePicker(0);
|
d = finishNewDateTimePicker(0);
|
||||||
d = (struct datetimepicker *) dtp;
|
|
||||||
setDateTimeFormat(d->hwnd);
|
setDateTimeFormat(d->hwnd);
|
||||||
if (SetWindowSubclass(d->hwnd, datetimepickerSubProc, 0, (DWORD_PTR) d) == FALSE)
|
if (SetWindowSubclass(d->hwnd, datetimepickerSubProc, 0, (DWORD_PTR) d) == FALSE)
|
||||||
logLastError("error subclassing date-time-picker to assist in locale change handling in uiNewDateTimePicker()");
|
logLastError("error subclassing date-time-picker to assist in locale change handling in uiNewDateTimePicker()");
|
||||||
return dtp;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
uiDateTimePicker *uiNewDatePicker(void)
|
uiDateTimePicker *uiNewDatePicker(void)
|
|
@ -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;
|
||||||
|
}
|
|
@ -1,42 +1,34 @@
|
||||||
// 11 april 2015
|
// 11 april 2015
|
||||||
#include "uipriv_windows.h"
|
#include "uipriv_windows.h"
|
||||||
|
|
||||||
struct label {
|
struct uiLabel {
|
||||||
uiLabel l;
|
uiWindowsControl c;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
uiDefineControlType(uiLabel, uiTypeLabel, struct label)
|
uiWindowsDefineControl(
|
||||||
|
uiLabel, // type name
|
||||||
static uintptr_t labelHandle(uiControl *c)
|
uiLabelType // type function
|
||||||
{
|
)
|
||||||
struct label *l = (struct label *) c;
|
|
||||||
|
|
||||||
return (uintptr_t) (l->hwnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
|
// via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
|
||||||
#define labelHeight 8
|
#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);
|
*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);
|
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);
|
uiWindowsUtilSetText(l->hwnd, text);
|
||||||
// changing the text might necessitate a change in the label's size
|
// changing the text might necessitate a change in the label's size
|
||||||
uiControlQueueResize(uiControl(l));
|
uiControlQueueResize(uiControl(l));
|
||||||
|
@ -44,10 +36,10 @@ static void labelSetText(uiLabel *ll, const char *text)
|
||||||
|
|
||||||
uiLabel *uiNewLabel(const char *text)
|
uiLabel *uiNewLabel(const char *text)
|
||||||
{
|
{
|
||||||
struct label *l;
|
uiLabel *l;
|
||||||
WCHAR *wtext;
|
WCHAR *wtext;
|
||||||
|
|
||||||
l = (struct label *) uiWindowsNewSingleHWNDControl(uiTypeLabel());
|
l = (uiLabel *) uiNewControl(uiLabelType());
|
||||||
|
|
||||||
wtext = toUTF16(text);
|
wtext = toUTF16(text);
|
||||||
l->hwnd = uiWindowsUtilCreateControlHWND(0,
|
l->hwnd = uiWindowsUtilCreateControlHWND(0,
|
||||||
|
@ -59,11 +51,7 @@ uiLabel *uiNewLabel(const char *text)
|
||||||
TRUE);
|
TRUE);
|
||||||
uiFree(wtext);
|
uiFree(wtext);
|
||||||
|
|
||||||
uiControl(l)->Handle = labelHandle;
|
uiWindowsFinishNewControl(l, uiLabel);
|
||||||
uiControl(l)->PreferredSize = labelPreferredSize;
|
|
||||||
|
|
||||||
uiLabel(l)->Text = labelText;
|
return l;
|
||||||
uiLabel(l)->SetText = labelSetText;
|
|
||||||
|
|
||||||
return uiLabel(l);
|
|
||||||
}
|
}
|
|
@ -1,25 +1,21 @@
|
||||||
// 19 may 2015
|
// 19 may 2015
|
||||||
#include "uipriv_windows.h"
|
#include "uipriv_windows.h"
|
||||||
|
|
||||||
struct progressbar {
|
struct uiProgressBar {
|
||||||
uiProgressBar p;
|
uiWindowsControl c;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
uiDefineControlType(uiProgressBar, uiTypeProgressBar, struct progressbar)
|
uiWindowsDefineControl(
|
||||||
|
uiProgressBar, // type name
|
||||||
static uintptr_t progressbarHandle(uiControl *c)
|
uiProgressBarType // type function
|
||||||
{
|
)
|
||||||
struct progressbar *p = (struct progressbar *) c;
|
|
||||||
|
|
||||||
return (uintptr_t) (p->hwnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
|
// via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
|
||||||
#define pbarWidth 237
|
#define pbarWidth 237
|
||||||
#define pbarHeight 8
|
#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);
|
*width = uiWindowsDlgUnitsToX(pbarWidth, d->Sys->BaseX);
|
||||||
*height = uiWindowsDlgUnitsToY(pbarHeight, d->Sys->BaseY);
|
*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
|
// 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
|
// see http://stackoverflow.com/questions/2217688/windows-7-aero-theme-progress-bar-bug
|
||||||
// it's not ideal/perfect, but it will have to do
|
// 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)
|
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
|
if (value == 100) { // because we can't 101
|
||||||
SendMessageW(p->hwnd, PBM_SETRANGE32, 0, 101);
|
SendMessageW(p->hwnd, PBM_SETRANGE32, 0, 101);
|
||||||
SendMessageW(p->hwnd, PBM_SETPOS, 101, 0);
|
SendMessageW(p->hwnd, PBM_SETPOS, 101, 0);
|
||||||
|
@ -48,9 +42,9 @@ static void progressbarSetValue(uiProgressBar *pp, int value)
|
||||||
|
|
||||||
uiProgressBar *uiNewProgressBar(void)
|
uiProgressBar *uiNewProgressBar(void)
|
||||||
{
|
{
|
||||||
struct progressbar *p;
|
uiProgressBar *p;
|
||||||
|
|
||||||
p = (struct progressbar *) uiWindowsNewSingleHWNDControl(uiTypeProgressBar());
|
p = (uiProgressBar *) uiNewControl(uiProgressBarType());
|
||||||
|
|
||||||
p->hwnd = uiWindowsUtilCreateControlHWND(0,
|
p->hwnd = uiWindowsUtilCreateControlHWND(0,
|
||||||
PROGRESS_CLASSW, L"",
|
PROGRESS_CLASSW, L"",
|
||||||
|
@ -58,10 +52,7 @@ uiProgressBar *uiNewProgressBar(void)
|
||||||
hInstance, NULL,
|
hInstance, NULL,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
||||||
uiControl(p)->Handle = progressbarHandle;
|
uiWindowsFinishNewControl(p, uiProgressBar);
|
||||||
uiControl(p)->PreferredSize = progressbarPreferredSize;
|
|
||||||
|
|
||||||
uiProgressBar(p)->SetValue = progressbarSetValue;
|
return p;
|
||||||
|
|
||||||
return uiProgressBar(p);
|
|
||||||
}
|
}
|
|
@ -5,24 +5,20 @@
|
||||||
// - http://stackoverflow.com/questions/2892703/how-do-i-draw-separators
|
// - 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
|
// - https://msdn.microsoft.com/en-us/library/windows/desktop/dn742405%28v=vs.85%29.aspx
|
||||||
|
|
||||||
struct separator {
|
struct uiSeparator {
|
||||||
uiSeparator s;
|
uiWindowsControl c;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
uiDefineControlType(uiSeparator, uiTypeSeparator, struct separator)
|
uiWindowsDefineControl(
|
||||||
|
uiSeparator, // type name
|
||||||
static uintptr_t separatorHandle(uiControl *c)
|
uiSeparatorType // type function
|
||||||
{
|
)
|
||||||
struct separator *s = (struct separator *) c;
|
|
||||||
|
|
||||||
return (uintptr_t) (s->hwnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// via https://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx
|
// via https://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx
|
||||||
#define separatorHeight 1
|
#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
|
*width = 1; // TODO
|
||||||
*height = uiWindowsDlgUnitsToY(separatorHeight, d->Sys->BaseY);
|
*height = uiWindowsDlgUnitsToY(separatorHeight, d->Sys->BaseY);
|
||||||
|
@ -30,9 +26,9 @@ static void separatorPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, i
|
||||||
|
|
||||||
uiSeparator *uiNewHorizontalSeparator(void)
|
uiSeparator *uiNewHorizontalSeparator(void)
|
||||||
{
|
{
|
||||||
struct separator *s;
|
uiSeparator *s;
|
||||||
|
|
||||||
s = (struct separator *) uiWindowsNewSingleHWNDControl(uiTypeSeparator());
|
s = (uiSeparator *) uiNewControl(uiSeparatorType());
|
||||||
|
|
||||||
s->hwnd = uiWindowsUtilCreateControlHWND(0,
|
s->hwnd = uiWindowsUtilCreateControlHWND(0,
|
||||||
L"static", L"",
|
L"static", L"",
|
||||||
|
@ -40,8 +36,7 @@ uiSeparator *uiNewHorizontalSeparator(void)
|
||||||
hInstance, NULL,
|
hInstance, NULL,
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
uiControl(s)->Handle = separatorHandle;
|
uiWindowsFinishNewControl(s, uiSeparator);
|
||||||
uiControl(s)->PreferredSize = separatorPreferredSize;
|
|
||||||
|
|
||||||
return uiSeparator(s);
|
return s;
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
|
131
windows/entry.c
131
windows/entry.c
|
@ -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);
|
|
||||||
}
|
|
107
windows/slider.c
107
windows/slider.c
|
@ -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);
|
|
||||||
}
|
|
Loading…
Reference in New Issue