2014-02-11 15:14:15 -06:00
|
|
|
// 11 february 2014
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2014-02-11 17:50:33 -06:00
|
|
|
"fmt"
|
2014-02-11 15:14:15 -06:00
|
|
|
"syscall"
|
|
|
|
"unsafe"
|
2014-02-12 09:35:15 -06:00
|
|
|
"sync"
|
2014-02-11 15:14:15 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
type sysData struct {
|
|
|
|
cSysData
|
|
|
|
|
2014-02-11 17:50:33 -06:00
|
|
|
hwnd _HWND
|
2014-02-12 20:08:10 -06:00
|
|
|
children map[_HMENU]*sysData
|
|
|
|
nextChildID _HMENU
|
|
|
|
childrenLock sync.Mutex
|
2014-02-11 17:50:33 -06:00
|
|
|
shownAlready bool
|
2014-02-11 15:14:15 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type classData struct {
|
2014-02-11 18:52:39 -06:00
|
|
|
name string
|
2014-02-11 15:14:15 -06:00
|
|
|
style uint32
|
|
|
|
xstyle uint32
|
2014-02-12 09:35:15 -06:00
|
|
|
mkid bool
|
2014-02-11 15:14:15 -06:00
|
|
|
}
|
|
|
|
|
2014-02-12 10:29:20 -06:00
|
|
|
const controlstyle = _WS_CHILD | _WS_VISIBLE | _WS_TABSTOP
|
|
|
|
const controlxstyle = 0
|
2014-02-11 15:14:15 -06:00
|
|
|
|
|
|
|
var classTypes = [nctypes]*classData{
|
|
|
|
c_window: &classData{
|
2014-02-11 17:50:33 -06:00
|
|
|
style: _WS_OVERLAPPEDWINDOW,
|
|
|
|
xstyle: 0,
|
2014-02-11 15:14:15 -06:00
|
|
|
},
|
2014-02-12 10:29:20 -06:00
|
|
|
c_button: &classData{
|
|
|
|
name: "BUTTON",
|
|
|
|
style: _BS_PUSHBUTTON | controlstyle,
|
|
|
|
xstyle: 0 | controlxstyle,
|
|
|
|
},
|
2014-02-11 15:14:15 -06:00
|
|
|
}
|
|
|
|
|
2014-02-12 20:08:10 -06:00
|
|
|
func (s *sysData) addChild(chlid *sysData) _HMENU {
|
|
|
|
s.childrenLock.Lock()
|
|
|
|
defer s.childrenLock.Unlock()
|
|
|
|
s.nextChildID++ // start at 1
|
|
|
|
s.children[s.nextChildID] = child
|
|
|
|
return s.nextChildID
|
|
|
|
}
|
2014-02-12 09:35:15 -06:00
|
|
|
|
2014-02-12 20:08:10 -06:00
|
|
|
func (s *sysData) delChild(id _HMENU) {
|
|
|
|
s.childrenLock.Lock()
|
|
|
|
defer s.childrenLock.Unlock()
|
|
|
|
delete(s.children, id)
|
2014-02-12 09:35:15 -06:00
|
|
|
}
|
|
|
|
|
2014-02-12 20:08:10 -06:00
|
|
|
func (s *sysData) make(initText string, initWidth int, initHeight int, window *sysData) (err error) {
|
2014-02-11 17:50:33 -06:00
|
|
|
ret := make(chan uiret)
|
|
|
|
defer close(ret)
|
|
|
|
ct := classTypes[s.ctype]
|
2014-02-12 20:28:58 -06:00
|
|
|
classname := ct.name
|
2014-02-12 20:08:10 -06:00
|
|
|
cid := _HMENU(0)
|
2014-02-12 10:29:20 -06:00
|
|
|
pwin := uintptr(_NULL)
|
2014-02-12 20:08:10 -06:00
|
|
|
if window != nil { // this is a child control
|
|
|
|
cid = window.addChild(s)
|
|
|
|
pwin = uintptr(window.hwnd)
|
2014-02-12 20:28:58 -06:00
|
|
|
} else { // need a new class
|
|
|
|
n, err := registerStdWndClass(s)
|
|
|
|
if err != nil {
|
|
|
|
return r.err
|
|
|
|
}
|
|
|
|
classname = n
|
2014-02-12 09:35:15 -06:00
|
|
|
}
|
2014-02-11 17:50:33 -06:00
|
|
|
uitask <- &uimsg{
|
|
|
|
call: _createWindowEx,
|
|
|
|
p: []uintptr{
|
|
|
|
uintptr(ct.xstyle),
|
2014-02-12 20:28:58 -06:00
|
|
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(classname))),
|
2014-02-12 09:43:57 -06:00
|
|
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(initText))),
|
2014-02-11 17:50:33 -06:00
|
|
|
uintptr(ct.style),
|
|
|
|
uintptr(_CW_USEDEFAULT), // TODO
|
|
|
|
uintptr(_CW_USEDEFAULT),
|
2014-02-12 09:51:27 -06:00
|
|
|
uintptr(initWidth),
|
|
|
|
uintptr(initHeight),
|
2014-02-12 10:29:20 -06:00
|
|
|
pwin,
|
2014-02-12 20:08:10 -06:00
|
|
|
uintptr(cid),
|
2014-02-11 17:50:33 -06:00
|
|
|
uintptr(hInstance),
|
|
|
|
uintptr(_NULL),
|
|
|
|
},
|
2014-02-11 18:09:10 -06:00
|
|
|
ret: ret,
|
2014-02-11 17:50:33 -06:00
|
|
|
}
|
|
|
|
r := <-ret
|
2014-02-11 18:34:28 -06:00
|
|
|
if r.ret == 0 { // failure
|
2014-02-12 20:08:10 -06:00
|
|
|
if window != nil {
|
|
|
|
window.delChild(cid)
|
|
|
|
}
|
2014-02-11 17:50:33 -06:00
|
|
|
return r.err
|
|
|
|
}
|
|
|
|
s.hwnd = _HWND(r.ret)
|
|
|
|
return nil
|
2014-02-11 15:14:15 -06:00
|
|
|
}
|
|
|
|
|
2014-02-11 17:50:33 -06:00
|
|
|
var (
|
|
|
|
_updateWindow = user32.NewProc("UpdateWindow")
|
|
|
|
)
|
|
|
|
|
|
|
|
// if the object is a window, we need to do the following the first time
|
|
|
|
// ShowWindow(hwnd, nCmdShow);
|
|
|
|
// UpdateWindow(hwnd);
|
|
|
|
// otherwise we go ahead and show the object normally with SW_SHOW
|
2014-02-11 15:14:15 -06:00
|
|
|
func (s *sysData) show() (err error) {
|
2014-02-11 17:50:33 -06:00
|
|
|
if s.ctype != c_window { // don't do the init ShowWindow/UpdateWindow chain on non-windows
|
|
|
|
s.shownAlready = true
|
|
|
|
}
|
|
|
|
show := uintptr(_SW_SHOW)
|
|
|
|
if !s.shownAlready {
|
|
|
|
show = uintptr(nCmdShow)
|
|
|
|
}
|
2014-02-11 15:14:15 -06:00
|
|
|
ret := make(chan uiret)
|
|
|
|
defer close(ret)
|
2014-02-11 19:23:49 -06:00
|
|
|
// TODO figure out how to handle error
|
2014-02-11 15:14:15 -06:00
|
|
|
uitask <- &uimsg{
|
2014-02-11 15:23:38 -06:00
|
|
|
call: _showWindow,
|
2014-02-11 18:09:10 -06:00
|
|
|
p: []uintptr{uintptr(s.hwnd), show},
|
2014-02-11 15:14:15 -06:00
|
|
|
ret: ret,
|
|
|
|
}
|
2014-02-11 19:23:49 -06:00
|
|
|
<-ret
|
2014-02-11 17:50:33 -06:00
|
|
|
if !s.shownAlready {
|
|
|
|
uitask <- &uimsg{
|
|
|
|
call: _updateWindow,
|
|
|
|
p: []uintptr{uintptr(s.hwnd)},
|
|
|
|
ret: ret,
|
|
|
|
}
|
2014-02-11 19:23:49 -06:00
|
|
|
r := <-ret
|
2014-02-11 17:50:33 -06:00
|
|
|
if r.ret == 0 { // failure
|
|
|
|
return fmt.Errorf("error updating window for the first time: %v", r.err)
|
|
|
|
}
|
|
|
|
s.shownAlready = true
|
|
|
|
}
|
|
|
|
return nil
|
2014-02-11 15:14:15 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) hide() (err error) {
|
|
|
|
ret := make(chan uiret)
|
|
|
|
defer close(ret)
|
2014-02-11 19:23:49 -06:00
|
|
|
// TODO figure out how to handle error
|
2014-02-11 15:14:15 -06:00
|
|
|
uitask <- &uimsg{
|
|
|
|
call: _showWindow,
|
|
|
|
p: []uintptr{uintptr(s.hwnd), _SW_HIDE},
|
|
|
|
ret: ret,
|
|
|
|
}
|
2014-02-11 19:23:49 -06:00
|
|
|
<-ret
|
|
|
|
return nil
|
2014-02-11 15:14:15 -06:00
|
|
|
}
|
2014-02-12 17:14:37 -06:00
|
|
|
|
|
|
|
func (s *sysData) setText(text string) error {
|
|
|
|
ret := make(chan uiret)
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- &uimsg{
|
|
|
|
call: _setWindowText,
|
|
|
|
p: []uintptr{
|
|
|
|
uintptr(s.hwnd),
|
|
|
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))),
|
|
|
|
},
|
|
|
|
ret: ret,
|
|
|
|
}
|
|
|
|
r := <-ret
|
|
|
|
if r.ret == 0 { // failure
|
|
|
|
return r.err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|