diff options
| author | Pietro Gagliardi <[email protected]> | 2014-11-01 08:35:21 -0400 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2014-11-01 08:35:21 -0400 |
| commit | aafd93b079b90d797140ee6d75c6d7acf71e73e4 (patch) | |
| tree | c532a65a6ae7106b1d552e56d2d22a0d0e887741 | |
| parent | 7d99cde8ad75aa0318c2703f0fa568e79863ea23 (diff) | |
Started handling Spinbox events on Windows.
| -rw-r--r-- | basicctrls_windows.c | 27 | ||||
| -rw-r--r-- | spinbox_windows.go | 24 | ||||
| -rw-r--r-- | winapi_windows.h | 2 |
3 files changed, 45 insertions, 8 deletions
diff --git a/basicctrls_windows.c b/basicctrls_windows.c index eefd4f8..0c5659f 100644 --- a/basicctrls_windows.c +++ b/basicctrls_windows.c @@ -161,7 +161,30 @@ void setGroupSubclass(HWND hwnd, void *data) xpanic("error subclassing Group to give it its own event handler", GetLastError()); } -HWND newUpDown(HWND prevUpDown) +static LRESULT CALLBACK updownSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data) +{ + NMHDR *nmhdr = (NMHDR *) lParam; + + switch (uMsg) { + case msgNOTIFY: + switch (nmhdr->code) { + case UDN_DELTAPOS: + spinboxUpDownClicked((void *) data, (NMUPDOWN *) lParam); + return FALSE; // allow change + } + return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); + case WM_NCDESTROY: + if ((*fv_RemoveWindowSubclass)(hwnd, updownSubProc, id) == FALSE) + xpanic("error removing Spinbox up-down control subclass (which was for its own event handler)", GetLastError()); + return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); + default: + return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); + } + xmissedmsg("Spinbox up-down control", "updownSubProc()", uMsg); + return 0; // unreached +} + +HWND newUpDown(HWND prevUpDown, void *data) { HWND hwnd; HWND parent; @@ -183,5 +206,7 @@ HWND newUpDown(HWND prevUpDown) parent, NULL, hInstance, NULL); if (hwnd == NULL) xpanic("error creating up-down control for Spinbox", GetLastError()); + if ((*fv_SetWindowSubclass)(hwnd, updownSubProc, 0, (DWORD_PTR) data) == FALSE) + xpanic("error subclassing Spinbox up-down control to give it its own event handler", GetLastError()); return hwnd; } diff --git a/spinbox_windows.go b/spinbox_windows.go index 7069706..5e64818 100644 --- a/spinbox_windows.go +++ b/spinbox_windows.go @@ -15,6 +15,7 @@ import "C" type spinbox struct { hwndEdit C.HWND hwndUpDown C.HWND + changed *event // updown state updownVisible bool // keep these here to avoid having to get them out @@ -28,6 +29,7 @@ func newSpinbox(min int, max int) Spinbox { s.hwndEdit = C.newControl(editclass, C.textfieldStyle | C.ES_NUMBER, C.textfieldExtStyle) + s.changed = newEvent() s.updownVisible = true // initially shown s.min = min s.max = max @@ -37,10 +39,7 @@ func newSpinbox(min int, max int) Spinbox { } func (s *spinbox) Value() int { - // TODO TODO TODO TODO TODO - // this CAN error out!!! - // we need to update s.value but we need to implement events first - return int(C.SendMessageW(s.hwndUpDown, C.UDM_GETPOS32, 0, 0)) + return s.value } func (s *spinbox) SetValue(value int) { @@ -55,6 +54,19 @@ func (s *spinbox) SetValue(value int) { C.SendMessageW(s.hwndUpDown, C.UDM_SETPOS32, 0, C.LPARAM(value)) } +func (s *spinbox) OnChanged(e func()) { + s.changed.set(e) +} + +//export spinboxUpDownClicked +func spinboxUpDownClicked(data unsafe.Pointer, nud *C.NMUPDOWN) { + // this is where we do custom increments + s := (*spinbox)(data) + // TODO this is allowed to go beyond the limits in wine? + s.value = int(nud.iPos + nud.iDelta) + s.changed.fire() +} + func (s *spinbox) setParent(p *controlParent) { C.controlSetParent(s.hwndEdit, p.hwnd) C.controlSetParent(s.hwndUpDown, p.hwnd) @@ -65,8 +77,8 @@ func (s *spinbox) setParent(p *controlParent) { // alas, we have to make a new up/down control each time :( // TODO we'll need to store a copy of the current position and range for this func (s *spinbox) remakeUpDown() { - // destroying the previous one and setting the parent properly is handled here - s.hwndUpDown = C.newUpDown(s.hwndUpDown) + // destroying the previous one, setting the parent properly, and subclassing are handled here + s.hwndUpDown = C.newUpDown(s.hwndUpDown, unsafe.Pointer(s)) // for this to work, hwndUpDown needs to have rect [0 0 0 0] C.moveWindow(s.hwndUpDown, 0, 0, 0, 0) C.SendMessageW(s.hwndUpDown, C.UDM_SETBUDDY, C.WPARAM(uintptr(unsafe.Pointer(s.hwndEdit))), 0) diff --git a/winapi_windows.h b/winapi_windows.h index 0c8cc23..dec981f 100644 --- a/winapi_windows.h +++ b/winapi_windows.h @@ -75,7 +75,7 @@ extern void setTextFieldSubclass(HWND, void *); extern void textfieldSetAndShowInvalidBalloonTip(HWND, WCHAR *); extern void textfieldHideInvalidBalloonTip(HWND); extern void setGroupSubclass(HWND, void *); -extern HWND newUpDown(HWND); +extern HWND newUpDown(HWND, void *); // init_windows.c extern HINSTANCE hInstance; |
