summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--redo/common_windows.go10
-rw-r--r--redo/controls_windows.go45
-rw-r--r--redo/funcnames_windows.go1
-rw-r--r--redo/uitask_windows.go3
-rw-r--r--redo/window_windows.go3
-rw-r--r--redo/zwinconstgen.go2
6 files changed, 62 insertions, 2 deletions
diff --git a/redo/common_windows.go b/redo/common_windows.go
index d2cae60..30c0d75 100644
--- a/redo/common_windows.go
+++ b/redo/common_windows.go
@@ -46,3 +46,13 @@ func storelpParam(hwnd uintptr, lParam t_LPARAM) {
cs = (*s_CREATESTRUCTW)(unsafe.Pointer(uintptr(lParam)))
f_SetWindowLongPtrW(hwnd, c_GWLP_USERDATA, cs.lpCreateParams)
}
+
+func (w t_WPARAM) HIWORD() uint16 {
+ u := uintptr(w) & 0xFFFF0000
+ return uint16(u >> 16)
+}
+
+func (w t_WPARAM) LOWORD() uint16 {
+ u := uintptr(w) & 0x0000FFFF
+ return uint16(u)
+}
diff --git a/redo/controls_windows.go b/redo/controls_windows.go
index 3b73b48..dd4b8c9 100644
--- a/redo/controls_windows.go
+++ b/redo/controls_windows.go
@@ -5,6 +5,7 @@ package ui
import (
"fmt"
"syscall"
+ "unsafe"
)
type widgetbase struct {
@@ -73,8 +74,20 @@ func (w *widgetbase) settext(text string, results ...t_LRESULT) *Request {
}
}
+// all controls that have events receive the events themselves through subclasses
+// to do this, all windows (including the message-only window; see http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q104069) forward WM_COMMAND to each control with this function
+func forwardCommand(hwnd uintptr, uMsg t_UINT, wParam t_WPARAM, lParam t_LPARAM) t_LRESULT {
+ control := uintptr(lParam)
+ // don't generate an event if the control (if there is one) is unparented (a child of the message-only window)
+ if control != hNULL && f_IsChild(msgwin, control) == 0 {
+ return f_SendMessageW(control, msgCOMMAND, wParam, lParam)
+ }
+ return f_DefWindowProcW(hwnd, uMsg, wParam, lParam)
+}
+
type button struct {
*widgetbase
+ clicked *event
}
var buttonclass = syscall.StringToUTF16Ptr("BUTTON")
@@ -89,6 +102,7 @@ func newButton(text string) *Request {
setWindowText(w.hwnd, text, []t_LRESULT{c_FALSE})
c <- &button{
widgetbase: w,
+ clicked: newEvent(),
}
},
resp: c,
@@ -96,8 +110,14 @@ func newButton(text string) *Request {
}
func (b *button) OnClicked(e func(c Doer)) *Request {
- // TODO
- return nil
+ c := make(chan interface{})
+ return &Request{
+ op: func() {
+ b.clicked.set(e)
+ c <- struct{}{}
+ },
+ resp: c,
+ }
}
func (b *button) Text() *Request {
@@ -107,3 +127,24 @@ func (b *button) Text() *Request {
func (b *button) SetText(text string) *Request {
return b.settext(text)
}
+
+var buttonsubprocptr = syscall.NewCallback(buttonSubProc)
+
+func buttonSubProc(hwnd uintptr, uMsg t_UINT, wParam t_WPARAM, lParam t_LPARAM, id t_UINT_PTR, data t_DWORD_PTR) t_LRESULT {
+ b := (*button)(unsafe.Pointer(uintptr(data)))
+ switch uMsg {
+ case msgCOMMAND:
+ if wParam.HIWORD() == c_BN_CLICKED {
+ b.clicked.fire()
+ println("button clicked")
+ return 0
+ }
+ // TODO return
+ case c_WM_NCDESTROY:
+ // TODO remove
+ // TODO return
+ default:
+ // TODO return
+ }
+ panic(fmt.Errorf("Button message %d does not return a value (bug in buttonSubProc())", uMsg))
+}
diff --git a/redo/funcnames_windows.go b/redo/funcnames_windows.go
index 4a12430..005607f 100644
--- a/redo/funcnames_windows.go
+++ b/redo/funcnames_windows.go
@@ -38,3 +38,4 @@ package ui
// wfunc user32 GetDC uintptr uintptr
// wfunc gdi32 SelectObject uintptr uintptr uintptr
// wfunc user32 ReleaseDC uintptr uintptr uintptr
+// wfunc user32 IsChild uintptr uintptr uintptr,noerr
diff --git a/redo/uitask_windows.go b/redo/uitask_windows.go
index 6c5b974..8e8187a 100644
--- a/redo/uitask_windows.go
+++ b/redo/uitask_windows.go
@@ -11,6 +11,7 @@ import (
// global messages unique to everything
const (
msgRequest = c_WM_APP + 1 + iota // + 1 just to be safe
+ msgCOMMAND // WM_COMMAND proxy; see forwardCommand() in controls_windows.go
)
var msgwin uintptr
@@ -91,6 +92,8 @@ func makemsgwin() error {
func msgwinproc(hwnd uintptr, uMsg t_UINT, wParam t_WPARAM, lParam t_LPARAM) t_LRESULT {
switch uMsg {
+ case c_WM_COMMAND:
+ return forwardCommand(hwnd, uMsg, wParam, lParam)
case msgRequest:
req := (*Request)(unsafe.Pointer(uintptr(lParam)))
perform(req)
diff --git a/redo/window_windows.go b/redo/window_windows.go
index 9bf0b26..c58d028 100644
--- a/redo/window_windows.go
+++ b/redo/window_windows.go
@@ -160,6 +160,7 @@ func (w *window) OnClosing(e func(Doer) bool) *Request {
}
}
+// TODO msg -> uMsg
func windowWndProc(hwnd uintptr, msg t_UINT, wParam t_WPARAM, lParam t_LPARAM) t_LRESULT {
w := (*window)(unsafe.Pointer(f_GetWindowLongPtrW(hwnd, c_GWLP_USERDATA)))
if w == nil {
@@ -173,6 +174,8 @@ func windowWndProc(hwnd uintptr, msg t_UINT, wParam t_WPARAM, lParam t_LPARAM) t
return f_DefWindowProcW(hwnd, msg, wParam, lParam)
}
switch msg {
+ case c_WM_COMMAND:
+ return forwardCommand(hwnd, msg, wParam, lParam)
case c_WM_SIZE:
var r s_RECT
diff --git a/redo/zwinconstgen.go b/redo/zwinconstgen.go
index 28ff843..c0e2171 100644
--- a/redo/zwinconstgen.go
+++ b/redo/zwinconstgen.go
@@ -276,6 +276,8 @@ func main() {
fmt.Fprintf(buf, "type t_WPARAM %s\n", winName(reflect.TypeOf(C.WPARAM(0))))
fmt.Fprintf(buf, "type t_LPARAM %s\n", winName(reflect.TypeOf(C.LPARAM(0))))
fmt.Fprintf(buf, "type t_LRESULT %s\n", winName(reflect.TypeOf(C.LRESULT(0))))
+ fmt.Fprintf(buf, "type t_UINT_PTR %s\n", winName(reflect.TypeOf(C.UINT_PTR(0))))
+ fmt.Fprintf(buf, "type t_DWORD_PTR %s\n", winName(reflect.TypeOf(C.DWORD_PTR(0))))
// and one for GetMessageW()
fmt.Fprintf(buf, "type t_BOOL %s\n", winName(reflect.TypeOf(C.BOOL(0))))