Laid down the framework for control events on Windows. The only problem left is that we need to use functions from comctl32.dll, so it's time to bring that blob of code back.

This commit is contained in:
Pietro Gagliardi 2014-07-17 15:10:26 -04:00
parent 1a712d4064
commit 19f7b2946a
6 changed files with 62 additions and 2 deletions

View File

@ -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)
}

View File

@ -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))
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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))))