Made sysdata_windows.go send func()s to uitask and not uimsgs. This is also more correct, as multi-step processes happen in one homogenous blob instead of in steps spread across two goroutines.
This commit is contained in:
parent
c159bb2018
commit
af2e8c4b13
|
@ -144,26 +144,25 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *sysData) make(window *sysData) (err error) {
|
func (s *sysData) make(window *sysData) (err error) {
|
||||||
ret := make(chan uiret)
|
ret := make(chan struct{})
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
ct := classTypes[s.ctype]
|
uitask <- func() {
|
||||||
cid := _HMENU(0)
|
ct := classTypes[s.ctype]
|
||||||
pwin := uintptr(_NULL)
|
cid := _HMENU(0)
|
||||||
if window != nil { // this is a child control
|
pwin := uintptr(_NULL)
|
||||||
cid = window.addChild(s)
|
if window != nil { // this is a child control
|
||||||
pwin = uintptr(window.hwnd)
|
cid = window.addChild(s)
|
||||||
}
|
pwin = uintptr(window.hwnd)
|
||||||
style := uintptr(ct.style)
|
}
|
||||||
if s.alternate {
|
style := uintptr(ct.style)
|
||||||
style = uintptr(ct.altStyle)
|
if s.alternate {
|
||||||
}
|
style = uintptr(ct.altStyle)
|
||||||
lpParam := uintptr(_NULL)
|
}
|
||||||
if ct.storeSysData {
|
lpParam := uintptr(_NULL)
|
||||||
lpParam = uintptr(unsafe.Pointer(s))
|
if ct.storeSysData {
|
||||||
}
|
lpParam = uintptr(unsafe.Pointer(s))
|
||||||
uitask <- &uimsg{
|
}
|
||||||
call: _createWindowEx,
|
r1, _, err := _createWindowEx.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(ct.xstyle),
|
uintptr(ct.xstyle),
|
||||||
utf16ToArg(ct.name),
|
utf16ToArg(ct.name),
|
||||||
blankString, // we set the window text later
|
blankString, // we set the window text later
|
||||||
|
@ -175,35 +174,28 @@ func (s *sysData) make(window *sysData) (err error) {
|
||||||
pwin,
|
pwin,
|
||||||
uintptr(cid),
|
uintptr(cid),
|
||||||
uintptr(hInstance),
|
uintptr(hInstance),
|
||||||
lpParam,
|
lpParam)
|
||||||
},
|
if r1 == 0 { // failure
|
||||||
ret: ret,
|
if window != nil {
|
||||||
}
|
window.delChild(cid)
|
||||||
r := <-ret
|
}
|
||||||
if r.ret == 0 { // failure
|
panic(fmt.Errorf("error actually creating window/control: %v", err))
|
||||||
if window != nil {
|
|
||||||
window.delChild(cid)
|
|
||||||
}
|
}
|
||||||
return fmt.Errorf("error actually creating window/control: %v", r.err)
|
if !ct.storeSysData { // regular control; store s.hwnd ourselves
|
||||||
}
|
s.hwnd = _HWND(r1)
|
||||||
if !ct.storeSysData { // regular control; store s.hwnd ourselves
|
} else if s.hwnd != _HWND(r1) { // we store sysData in storeSysData(); sanity check
|
||||||
s.hwnd = _HWND(r.ret)
|
panic(fmt.Errorf("hwnd mismatch creating window/control: storeSysData() stored 0x%X but CreateWindowEx() returned 0x%X", s.hwnd, r1))
|
||||||
} else if s.hwnd != _HWND(r.ret) { // we store sysData in storeSysData(); sanity check
|
}
|
||||||
panic(fmt.Errorf("hwnd mismatch creating window/control: storeSysData() stored 0x%X but CreateWindowEx() returned 0x%X", s.hwnd, ret))
|
if !ct.doNotLoadFont {
|
||||||
}
|
_sendMessage.Call(
|
||||||
if !ct.doNotLoadFont {
|
|
||||||
uitask <- &uimsg{
|
|
||||||
call: _sendMessage,
|
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(_WM_SETFONT),
|
uintptr(_WM_SETFONT),
|
||||||
uintptr(_WPARAM(controlFont)),
|
uintptr(_WPARAM(controlFont)),
|
||||||
uintptr(_LPARAM(_TRUE)),
|
uintptr(_LPARAM(_TRUE)))
|
||||||
},
|
|
||||||
ret: ret,
|
|
||||||
}
|
}
|
||||||
<-ret
|
ret <- struct{}{}
|
||||||
}
|
}
|
||||||
|
<-ret
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,75 +207,63 @@ var (
|
||||||
// ShowWindow(hwnd, nCmdShow);
|
// ShowWindow(hwnd, nCmdShow);
|
||||||
// UpdateWindow(hwnd);
|
// UpdateWindow(hwnd);
|
||||||
func (s *sysData) firstShow() error {
|
func (s *sysData) firstShow() error {
|
||||||
ret := make(chan uiret)
|
ret := make(chan struct{})
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _showWindow,
|
_showWindow.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(nCmdShow),
|
uintptr(nCmdShow))
|
||||||
},
|
r1, _, err := _updateWindow.Call(uintptr(s.hwnd))
|
||||||
ret: ret,
|
if r1 == 0 { // failure
|
||||||
|
panic(fmt.Errorf("error updating window for the first time: %v", err))
|
||||||
|
}
|
||||||
|
ret <- struct{}{}
|
||||||
}
|
}
|
||||||
<-ret
|
<-ret
|
||||||
uitask <- &uimsg{
|
|
||||||
call: _updateWindow,
|
|
||||||
p: []uintptr{uintptr(s.hwnd)},
|
|
||||||
ret: ret,
|
|
||||||
}
|
|
||||||
r := <-ret
|
|
||||||
if r.ret == 0 { // failure
|
|
||||||
return fmt.Errorf("error updating window for the first time: %v", r.err)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) show() {
|
func (s *sysData) show() {
|
||||||
ret := make(chan uiret)
|
ret := make(chan struct{})
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _showWindow,
|
_showWindow.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(_SW_SHOW),
|
uintptr(_SW_SHOW))
|
||||||
},
|
ret <- struct{}{}
|
||||||
ret: ret,
|
|
||||||
}
|
}
|
||||||
<-ret
|
<-ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) hide() {
|
func (s *sysData) hide() {
|
||||||
ret := make(chan uiret)
|
ret := make(chan struct{})
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _showWindow,
|
_showWindow.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(_SW_HIDE),
|
uintptr(_SW_HIDE))
|
||||||
},
|
ret <- struct{}{}
|
||||||
ret: ret,
|
|
||||||
}
|
}
|
||||||
<-ret
|
<-ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setText(text string) {
|
func (s *sysData) setText(text string) {
|
||||||
ptext := toUTF16(text)
|
ret := make(chan struct{})
|
||||||
ret := make(chan uiret)
|
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _setWindowText,
|
ptext := toUTF16(text)
|
||||||
p: []uintptr{
|
r1, _, err := _setWindowText.Call(
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
utf16ToArg(ptext),
|
utf16ToArg(ptext))
|
||||||
},
|
if r1 == 0 { // failure
|
||||||
ret: ret,
|
panic(fmt.Errorf("error setting window/control text: %v", err))
|
||||||
}
|
}
|
||||||
r := <-ret
|
ret <- struct{}{}
|
||||||
if r.ret == 0 { // failure
|
|
||||||
panic(fmt.Errorf("error setting window/control text: %v", r.err))
|
|
||||||
}
|
}
|
||||||
|
<-ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// runs on uitask
|
||||||
func (s *sysData) setRect(x int, y int, width int, height int, winheight int) error {
|
func (s *sysData) setRect(x int, y int, width int, height int, winheight int) error {
|
||||||
r1, _, err := _moveWindow.Call(
|
r1, _, err := _moveWindow.Call(
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
|
@ -299,277 +279,238 @@ func (s *sysData) setRect(x int, y int, width int, height int, winheight int) er
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) isChecked() bool {
|
func (s *sysData) isChecked() bool {
|
||||||
ret := make(chan uiret)
|
ret := make(chan bool)
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _sendMessage,
|
r1, _, _ := _sendMessage.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(_BM_GETCHECK),
|
uintptr(_BM_GETCHECK),
|
||||||
uintptr(0),
|
uintptr(0),
|
||||||
uintptr(0),
|
uintptr(0))
|
||||||
},
|
ret <- r1 == _BST_CHECKED
|
||||||
ret: ret,
|
|
||||||
}
|
}
|
||||||
r := <-ret
|
return <-ret
|
||||||
return r.ret == _BST_CHECKED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) text() (str string) {
|
func (s *sysData) text() (str string) {
|
||||||
var tc []uint16
|
ret := make(chan string)
|
||||||
|
|
||||||
ret := make(chan uiret)
|
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _sendMessage,
|
var tc []uint16
|
||||||
p: []uintptr{
|
|
||||||
|
r1, _, _ := _sendMessage.Call(
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(_WM_GETTEXTLENGTH),
|
uintptr(_WM_GETTEXTLENGTH),
|
||||||
uintptr(0),
|
uintptr(0),
|
||||||
uintptr(0),
|
uintptr(0))
|
||||||
},
|
length := r1 + 1 // terminating null
|
||||||
ret: ret,
|
tc = make([]uint16, length)
|
||||||
}
|
_sendMessage.Call(
|
||||||
r := <-ret
|
|
||||||
length := r.ret + 1 // terminating null
|
|
||||||
tc = make([]uint16, length)
|
|
||||||
uitask <- &uimsg{
|
|
||||||
call: _sendMessage,
|
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(_WM_GETTEXT),
|
uintptr(_WM_GETTEXT),
|
||||||
uintptr(_WPARAM(length)),
|
uintptr(_WPARAM(length)),
|
||||||
uintptr(_LPARAM(unsafe.Pointer(&tc[0]))),
|
uintptr(_LPARAM(unsafe.Pointer(&tc[0]))))
|
||||||
},
|
ret <- syscall.UTF16ToString(tc)
|
||||||
ret: ret,
|
|
||||||
}
|
}
|
||||||
<-ret
|
return <-ret
|
||||||
return syscall.UTF16ToString(tc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) append(what string) {
|
func (s *sysData) append(what string) {
|
||||||
pwhat := toUTF16(what)
|
ret := make(chan struct{})
|
||||||
ret := make(chan uiret)
|
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _sendMessage,
|
pwhat := toUTF16(what)
|
||||||
p: []uintptr{
|
r1, _, err := _sendMessage.Call(
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(classTypes[s.ctype].appendMsg),
|
uintptr(classTypes[s.ctype].appendMsg),
|
||||||
uintptr(_WPARAM(0)),
|
uintptr(_WPARAM(0)),
|
||||||
utf16ToLPARAM(pwhat),
|
utf16ToLPARAM(pwhat))
|
||||||
},
|
if r1 == uintptr(classTypes[s.ctype].addSpaceErr) {
|
||||||
ret: ret,
|
panic(fmt.Errorf("out of space adding item to combobox/listbox (last error: %v)", err))
|
||||||
}
|
} else if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) {
|
||||||
r := <-ret
|
panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", err))
|
||||||
if r.ret == uintptr(classTypes[s.ctype].addSpaceErr) {
|
}
|
||||||
panic(fmt.Errorf("out of space adding item to combobox/listbox (last error: %v)", r.err))
|
ret <- struct{}{}
|
||||||
} else if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) {
|
|
||||||
panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", r.err))
|
|
||||||
}
|
}
|
||||||
|
<-ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) insertBefore(what string, index int) {
|
func (s *sysData) insertBefore(what string, index int) {
|
||||||
pwhat := toUTF16(what)
|
ret := make(chan struct{})
|
||||||
ret := make(chan uiret)
|
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _sendMessage,
|
pwhat := toUTF16(what)
|
||||||
p: []uintptr{
|
r1, _, err := _sendMessage.Call(
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(classTypes[s.ctype].insertBeforeMsg),
|
uintptr(classTypes[s.ctype].insertBeforeMsg),
|
||||||
uintptr(_WPARAM(index)),
|
uintptr(_WPARAM(index)),
|
||||||
utf16ToLPARAM(pwhat),
|
utf16ToLPARAM(pwhat))
|
||||||
},
|
if r1 == uintptr(classTypes[s.ctype].addSpaceErr) {
|
||||||
ret: ret,
|
panic(fmt.Errorf("out of space adding item to combobox/listbox (last error: %v)", err))
|
||||||
|
} else if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) {
|
||||||
|
panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", err))
|
||||||
|
}
|
||||||
|
ret <- struct{}{}
|
||||||
}
|
}
|
||||||
r := <-ret
|
<-ret
|
||||||
if r.ret == uintptr(classTypes[s.ctype].addSpaceErr) {
|
}
|
||||||
panic(fmt.Errorf("out of space adding item to combobox/listbox (last error: %v)", r.err))
|
|
||||||
} else if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) {
|
// runs on uitask
|
||||||
panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", r.err))
|
func (s *sysData) doSelectedIndex() int {
|
||||||
|
r1, _, _ := _sendMessage.Call(
|
||||||
|
uintptr(s.hwnd),
|
||||||
|
uintptr(classTypes[s.ctype].selectedIndexMsg),
|
||||||
|
uintptr(_WPARAM(0)),
|
||||||
|
uintptr(_LPARAM(0)))
|
||||||
|
if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { // no selection or manually entered text (apparently, for the latter)
|
||||||
|
return -1
|
||||||
}
|
}
|
||||||
|
return int(r1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) selectedIndex() int {
|
func (s *sysData) selectedIndex() int {
|
||||||
ret := make(chan uiret)
|
ret := make(chan int)
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _sendMessage,
|
ret <- s.doSelectedIndex()
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
|
||||||
uintptr(classTypes[s.ctype].selectedIndexMsg),
|
|
||||||
uintptr(_WPARAM(0)),
|
|
||||||
uintptr(_LPARAM(0)),
|
|
||||||
},
|
|
||||||
ret: ret,
|
|
||||||
}
|
}
|
||||||
r := <-ret
|
return <-ret
|
||||||
if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) { // no selection or manually entered text (apparently, for the latter)
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
return int(r.ret)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) selectedIndices() []int {
|
// runs on uitask
|
||||||
|
func (s *sysData) doSelectedIndices() []int {
|
||||||
if !s.alternate { // single-selection list box; use single-selection method
|
if !s.alternate { // single-selection list box; use single-selection method
|
||||||
index := s.selectedIndex()
|
index := s.doSelectedIndex()
|
||||||
if index == -1 {
|
if index == -1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return []int{index}
|
return []int{index}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := make(chan uiret)
|
r1, _, err := _sendMessage.Call(
|
||||||
defer close(ret)
|
uintptr(s.hwnd),
|
||||||
uitask <- &uimsg{
|
uintptr(_LB_GETSELCOUNT),
|
||||||
call: _sendMessage,
|
uintptr(0),
|
||||||
p: []uintptr{
|
uintptr(0))
|
||||||
uintptr(s.hwnd),
|
if r1 == negConst(_LB_ERR) {
|
||||||
uintptr(_LB_GETSELCOUNT),
|
panic(fmt.Errorf("error: LB_ERR from LB_GETSELCOUNT in what we know is a multi-selection listbox: %v", err))
|
||||||
uintptr(0),
|
|
||||||
uintptr(0),
|
|
||||||
},
|
|
||||||
ret: ret,
|
|
||||||
}
|
}
|
||||||
r := <-ret
|
if r1 == 0 { // nothing selected
|
||||||
if r.ret == negConst(_LB_ERR) {
|
|
||||||
panic("UI library internal error: LB_ERR from LB_GETSELCOUNT in what we know is a multi-selection listbox")
|
|
||||||
}
|
|
||||||
if r.ret == 0 { // nothing selected
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
indices := make([]int, r.ret)
|
indices := make([]int, r1)
|
||||||
uitask <- &uimsg{
|
r1, _, err = _sendMessage.Call(
|
||||||
call: _sendMessage,
|
uintptr(s.hwnd),
|
||||||
p: []uintptr{
|
uintptr(_LB_GETSELITEMS),
|
||||||
uintptr(s.hwnd),
|
uintptr(_WPARAM(r1)),
|
||||||
uintptr(_LB_GETSELITEMS),
|
uintptr(_LPARAM(unsafe.Pointer(&indices[0]))))
|
||||||
uintptr(_WPARAM(r.ret)),
|
if r1 == negConst(_LB_ERR) {
|
||||||
uintptr(_LPARAM(unsafe.Pointer(&indices[0]))),
|
panic(fmt.Errorf("error: LB_ERR from LB_GETSELITEMS in what we know is a multi-selection listbox: %v", err))
|
||||||
},
|
|
||||||
ret: ret,
|
|
||||||
}
|
|
||||||
r = <-ret
|
|
||||||
if r.ret == negConst(_LB_ERR) {
|
|
||||||
panic("UI library internal error: LB_ERR from LB_GETSELITEMS in what we know is a multi-selection listbox")
|
|
||||||
}
|
}
|
||||||
return indices
|
return indices
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) selectedTexts() []string {
|
func (s *sysData) selectedIndices() []int {
|
||||||
indices := s.selectedIndices()
|
ret := make(chan []int)
|
||||||
ret := make(chan uiret)
|
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
strings := make([]string, len(indices))
|
uitask <- func() {
|
||||||
for i, v := range indices {
|
ret <- s.doSelectedIndices()
|
||||||
uitask <- &uimsg{
|
}
|
||||||
call: _sendMessage,
|
return <-ret
|
||||||
p: []uintptr{
|
}
|
||||||
|
|
||||||
|
func (s *sysData) selectedTexts() []string {
|
||||||
|
ret := make(chan []string)
|
||||||
|
defer close(ret)
|
||||||
|
uitask <- func() {
|
||||||
|
indices := s.doSelectedIndices()
|
||||||
|
strings := make([]string, len(indices))
|
||||||
|
for i, v := range indices {
|
||||||
|
r1, _, err := _sendMessage.Call(
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(_LB_GETTEXTLEN),
|
uintptr(_LB_GETTEXTLEN),
|
||||||
uintptr(_WPARAM(v)),
|
uintptr(_WPARAM(v)),
|
||||||
uintptr(0),
|
uintptr(0))
|
||||||
},
|
if r1 == negConst(_LB_ERR) {
|
||||||
ret: ret,
|
panic(fmt.Errorf("error: LB_ERR from LB_GETTEXTLEN in what we know is a valid listbox index (came from LB_GETSELITEMS): %v", err))
|
||||||
}
|
}
|
||||||
r := <-ret
|
str := make([]uint16, r1)
|
||||||
if r.ret == negConst(_LB_ERR) {
|
r1, _, err = _sendMessage.Call(
|
||||||
panic("UI library internal error: LB_ERR from LB_GETTEXTLEN in what we know is a valid listbox index (came from LB_GETSELITEMS)")
|
|
||||||
}
|
|
||||||
str := make([]uint16, r.ret)
|
|
||||||
uitask <- &uimsg{
|
|
||||||
call: _sendMessage,
|
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(_LB_GETTEXT),
|
uintptr(_LB_GETTEXT),
|
||||||
uintptr(_WPARAM(v)),
|
uintptr(_WPARAM(v)),
|
||||||
uintptr(_LPARAM(unsafe.Pointer(&str[0]))),
|
uintptr(_LPARAM(unsafe.Pointer(&str[0]))))
|
||||||
},
|
if r1 == negConst(_LB_ERR) {
|
||||||
ret: ret,
|
panic(fmt.Errorf("error: LB_ERR from LB_GETTEXT in what we know is a valid listbox index (came from LB_GETSELITEMS): %v", err))
|
||||||
|
}
|
||||||
|
strings[i] = syscall.UTF16ToString(str)
|
||||||
}
|
}
|
||||||
r = <-ret
|
ret <- strings
|
||||||
if r.ret == negConst(_LB_ERR) {
|
|
||||||
panic("UI library internal error: LB_ERR from LB_GETTEXT in what we know is a valid listbox index (came from LB_GETSELITEMS)")
|
|
||||||
}
|
|
||||||
strings[i] = syscall.UTF16ToString(str)
|
|
||||||
}
|
}
|
||||||
return strings
|
return <-ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setWindowSize(width int, height int) error {
|
func (s *sysData) setWindowSize(width int, height int) error {
|
||||||
var rect _RECT
|
ret := make(chan struct{})
|
||||||
|
|
||||||
ret := make(chan uiret)
|
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _getClientRect,
|
var rect _RECT
|
||||||
p: []uintptr{
|
|
||||||
|
r1, _, err := _getClientRect.Call(
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(unsafe.Pointer(&rect)),
|
uintptr(unsafe.Pointer(&rect)))
|
||||||
},
|
if r1 == 0 {
|
||||||
ret: ret,
|
panic(fmt.Errorf("error getting upper-left of window for resize: %v", err))
|
||||||
}
|
}
|
||||||
r := <-ret
|
// TODO AdjustWindowRect() on the result
|
||||||
if r.ret == 0 {
|
// 0 because (0,0) is top-left so no winheight
|
||||||
return fmt.Errorf("error getting upper-left of window for resize: %v", r.err)
|
err = s.setRect(int(rect.left), int(rect.top), width, height, 0)
|
||||||
}
|
if err != nil {
|
||||||
// 0 because (0,0) is top-left so no winheight
|
panic(fmt.Errorf("error actually resizing window: %v", err))
|
||||||
// TODO this needs to be run on uitask!
|
}
|
||||||
err := s.setRect(int(rect.left), int(rect.top), width, height, 0)
|
ret <- struct{}{}
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error actually resizing window: %v", err)
|
|
||||||
}
|
}
|
||||||
|
<-ret
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) delete(index int) {
|
func (s *sysData) delete(index int) {
|
||||||
ret := make(chan uiret)
|
ret := make(chan struct{})
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _sendMessage,
|
r1, _, err := _sendMessage.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(classTypes[s.ctype].deleteMsg),
|
uintptr(classTypes[s.ctype].deleteMsg),
|
||||||
uintptr(_WPARAM(index)),
|
uintptr(_WPARAM(index)),
|
||||||
uintptr(0),
|
uintptr(0))
|
||||||
},
|
if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) {
|
||||||
ret: ret,
|
panic(fmt.Errorf("failed to delete item from combobox/listbox (last error: %v)", err))
|
||||||
}
|
}
|
||||||
r := <-ret
|
ret <- struct{}{}
|
||||||
if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) {
|
|
||||||
panic(fmt.Errorf("failed to delete item from combobox/listbox (last error: %v)", r.err))
|
|
||||||
}
|
}
|
||||||
|
<-ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setIndeterminate() {
|
func (s *sysData) setIndeterminate() {
|
||||||
ret := make(chan uiret)
|
ret := make(chan struct{})
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _setWindowLongPtr,
|
r1, _, err := _setWindowLongPtr.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
negConst(_GWL_STYLE),
|
negConst(_GWL_STYLE),
|
||||||
uintptr(classTypes[s.ctype].style | _PBS_MARQUEE),
|
uintptr(classTypes[s.ctype].style | _PBS_MARQUEE))
|
||||||
},
|
if r1 == 0 {
|
||||||
ret: ret,
|
panic(fmt.Errorf("error setting progress bar style to enter indeterminate mode: %v", err))
|
||||||
}
|
}
|
||||||
r := <-ret
|
_sendMessage.Call(
|
||||||
if r.ret == 0 {
|
|
||||||
panic(fmt.Errorf("error setting progress bar style to enter indeterminate mode: %v", r.err))
|
|
||||||
}
|
|
||||||
uitask <- &uimsg{
|
|
||||||
call: _sendMessage,
|
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(_PBM_SETMARQUEE),
|
uintptr(_PBM_SETMARQUEE),
|
||||||
uintptr(_WPARAM(_TRUE)),
|
uintptr(_WPARAM(_TRUE)),
|
||||||
uintptr(0),
|
uintptr(0))
|
||||||
},
|
s.isMarquee = true
|
||||||
ret: ret,
|
ret <- struct{}{}
|
||||||
}
|
}
|
||||||
<-ret
|
<-ret
|
||||||
s.isMarquee = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setProgress(percent int) {
|
func (s *sysData) setProgress(percent int) {
|
||||||
|
@ -577,153 +518,116 @@ func (s *sysData) setProgress(percent int) {
|
||||||
s.setIndeterminate()
|
s.setIndeterminate()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ret := make(chan uiret)
|
ret := make(chan struct{})
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
if s.isMarquee {
|
uitask <- func() {
|
||||||
// turn off marquee before switching back
|
if s.isMarquee {
|
||||||
uitask <- &uimsg{
|
// turn off marquee before switching back
|
||||||
call: _sendMessage,
|
_sendMessage.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(_PBM_SETMARQUEE),
|
uintptr(_PBM_SETMARQUEE),
|
||||||
uintptr(_WPARAM(_FALSE)),
|
uintptr(_WPARAM(_FALSE)),
|
||||||
uintptr(0),
|
uintptr(0))
|
||||||
},
|
r1, _, err := _setWindowLongPtr.Call(
|
||||||
ret: ret,
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
uitask <- &uimsg{
|
|
||||||
call: _setWindowLongPtr,
|
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
negConst(_GWL_STYLE),
|
negConst(_GWL_STYLE),
|
||||||
uintptr(classTypes[s.ctype].style),
|
uintptr(classTypes[s.ctype].style))
|
||||||
},
|
if r1 == 0 {
|
||||||
ret: ret,
|
panic(fmt.Errorf("error setting progress bar style to leave indeterminate mode (percent %d): %v", percent, err))
|
||||||
|
}
|
||||||
|
s.isMarquee = false
|
||||||
}
|
}
|
||||||
r := <-ret
|
send := func(msg uintptr, n int, l _LPARAM) {
|
||||||
if r.ret == 0 {
|
_sendMessage.Call(
|
||||||
panic(fmt.Errorf("error setting progress bar style to leave indeterminate mode (percent %d): %v", percent, r.err))
|
|
||||||
}
|
|
||||||
s.isMarquee = false
|
|
||||||
}
|
|
||||||
send := func(msg uintptr, n int, l _LPARAM) {
|
|
||||||
uitask <- &uimsg{
|
|
||||||
call: _sendMessage,
|
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
msg,
|
msg,
|
||||||
uintptr(_WPARAM(n)),
|
uintptr(_WPARAM(n)),
|
||||||
uintptr(l),
|
uintptr(l))
|
||||||
},
|
|
||||||
ret: ret,
|
|
||||||
}
|
}
|
||||||
<-ret
|
// Windows 7 has a non-disableable slowly-animating progress bar increment
|
||||||
}
|
// there isn't one for decrement, so we'll work around by going one higher and then lower again
|
||||||
// Windows 7 has a non-disableable slowly-animating progress bar increment
|
// for the case where percent == 100, we need to increase the range temporarily
|
||||||
// there isn't one for decrement, so we'll work around by going one higher and then lower again
|
// sources: http://social.msdn.microsoft.com/Forums/en-US/61350dc7-6584-4c4e-91b0-69d642c03dae/progressbar-disable-smooth-animation http://stackoverflow.com/questions/2217688/windows-7-aero-theme-progress-bar-bug http://discuss.joelonsoftware.com/default.asp?dotnet.12.600456.2 http://stackoverflow.com/questions/22469876/progressbar-lag-when-setting-position-with-pbm-setpos http://stackoverflow.com/questions/6128287/tprogressbar-never-fills-up-all-the-way-seems-to-be-updating-too-fast
|
||||||
// for the case where percent == 100, we need to increase the range temporarily
|
if percent == 100 {
|
||||||
// this kind of thing is why I want to move away from uimsg and toward having uitask take func()s like on the other platforms
|
send(_PBM_SETRANGE32, 0, 101)
|
||||||
// sources: http://social.msdn.microsoft.com/Forums/en-US/61350dc7-6584-4c4e-91b0-69d642c03dae/progressbar-disable-smooth-animation http://stackoverflow.com/questions/2217688/windows-7-aero-theme-progress-bar-bug http://discuss.joelonsoftware.com/default.asp?dotnet.12.600456.2 http://stackoverflow.com/questions/22469876/progressbar-lag-when-setting-position-with-pbm-setpos http://stackoverflow.com/questions/6128287/tprogressbar-never-fills-up-all-the-way-seems-to-be-updating-too-fast
|
}
|
||||||
if percent == 100 {
|
send(_PBM_SETPOS, percent+1, 0)
|
||||||
send(_PBM_SETRANGE32, 0, 101)
|
send(_PBM_SETPOS, percent, 0)
|
||||||
}
|
if percent == 100 {
|
||||||
send(_PBM_SETPOS, percent+1, 0)
|
send(_PBM_SETRANGE32, 0, 100)
|
||||||
send(_PBM_SETPOS, percent, 0)
|
}
|
||||||
if percent == 100 {
|
ret <- struct{}{}
|
||||||
send(_PBM_SETRANGE32, 0, 100)
|
|
||||||
}
|
}
|
||||||
|
<-ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) len() int {
|
func (s *sysData) len() int {
|
||||||
ret := make(chan uiret)
|
ret := make(chan int)
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _sendMessage,
|
r1, _, err := _sendMessage.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(classTypes[s.ctype].lenMsg),
|
uintptr(classTypes[s.ctype].lenMsg),
|
||||||
uintptr(_WPARAM(0)),
|
uintptr(_WPARAM(0)),
|
||||||
uintptr(_LPARAM(0)),
|
uintptr(_LPARAM(0)))
|
||||||
},
|
if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) {
|
||||||
ret: ret,
|
panic(fmt.Errorf("unexpected error return from sysData.len(); GetLastError() says %v", err))
|
||||||
|
}
|
||||||
|
ret <- int(r1)
|
||||||
}
|
}
|
||||||
r := <-ret
|
return <-ret
|
||||||
if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) {
|
|
||||||
panic(fmt.Errorf("unexpected error return from sysData.len(); GetLastError() says %v", r.err))
|
|
||||||
}
|
|
||||||
return int(r.ret)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setAreaSize(width int, height int) {
|
func (s *sysData) setAreaSize(width int, height int) {
|
||||||
ret := make(chan uiret)
|
ret := make(chan struct{})
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _sendMessage,
|
_sendMessage.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(msgSetAreaSize),
|
uintptr(msgSetAreaSize),
|
||||||
uintptr(width), // WPARAM is UINT_PTR on Windows XP and newer at least, so we're good with this
|
uintptr(width), // WPARAM is UINT_PTR on Windows XP and newer at least, so we're good with this
|
||||||
uintptr(height),
|
uintptr(height))
|
||||||
},
|
ret <- struct{}{}
|
||||||
ret: ret,
|
|
||||||
}
|
}
|
||||||
<-ret
|
<-ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) repaintAll() {
|
func (s *sysData) repaintAll() {
|
||||||
ret := make(chan uiret)
|
ret := make(chan struct{})
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _sendMessage,
|
_sendMessage.Call(
|
||||||
p: []uintptr{
|
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(msgRepaintAll),
|
uintptr(msgRepaintAll),
|
||||||
uintptr(0),
|
uintptr(0),
|
||||||
uintptr(0),
|
uintptr(0))
|
||||||
},
|
ret <- struct{}{}
|
||||||
ret: ret,
|
|
||||||
}
|
}
|
||||||
<-ret
|
<-ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) center() {
|
func (s *sysData) center() {
|
||||||
var ws _RECT
|
ret := make(chan struct{})
|
||||||
|
|
||||||
ret := make(chan uiret)
|
|
||||||
defer close(ret)
|
defer close(ret)
|
||||||
uitask <- &uimsg{
|
uitask <- func() {
|
||||||
call: _getWindowRect,
|
var ws _RECT
|
||||||
p: []uintptr{
|
|
||||||
|
r1, _, err := _getWindowRect.Call(
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(unsafe.Pointer(&ws)),
|
uintptr(unsafe.Pointer(&ws)))
|
||||||
},
|
if r1 == 0 {
|
||||||
ret: ret,
|
panic(fmt.Errorf("error getting window rect for sysData.center(): %v", err))
|
||||||
|
}
|
||||||
|
// TODO should this be using the monitor functions instead? http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx
|
||||||
|
// error returns from GetSystemMetrics() is meaningless because the return value, 0, is still valid
|
||||||
|
dw, _, _ := _getSystemMetrics.Call(uintptr(_SM_CXFULLSCREEN))
|
||||||
|
dh, _, _ := _getSystemMetrics.Call(uintptr(_SM_CYFULLSCREEN))
|
||||||
|
ww := ws.right - ws.left
|
||||||
|
wh := ws.bottom - ws.top
|
||||||
|
wx := (int32(dw) / 2) - (ww / 2)
|
||||||
|
wy := (int32(dh) / 2) - (wh / 2)
|
||||||
|
s.setRect(int(wx), int(wy), int(ww), int(wh), 0)
|
||||||
|
ret <- struct{}{}
|
||||||
}
|
}
|
||||||
r := <-ret
|
<-ret
|
||||||
if r.ret == 0 {
|
|
||||||
panic(fmt.Errorf("error getting window rect for sysData.center(): %v", r.err))
|
|
||||||
}
|
|
||||||
// TODO should this be using the monitor functions instead? http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx
|
|
||||||
// error returns from GetSystemMetrics() is meaningless because the return value, 0, is still valid
|
|
||||||
uitask <- &uimsg{
|
|
||||||
call: _getSystemMetrics,
|
|
||||||
p: []uintptr{uintptr(_SM_CXFULLSCREEN)},
|
|
||||||
ret: ret,
|
|
||||||
}
|
|
||||||
r = <-ret
|
|
||||||
dw := r.ret
|
|
||||||
uitask <- &uimsg{
|
|
||||||
call: _getSystemMetrics,
|
|
||||||
p: []uintptr{uintptr(_SM_CYFULLSCREEN)},
|
|
||||||
ret: ret,
|
|
||||||
}
|
|
||||||
r = <-ret
|
|
||||||
dh := r.ret
|
|
||||||
ww := ws.right - ws.left
|
|
||||||
wh := ws.bottom - ws.top
|
|
||||||
wx := (int32(dw) / 2) - (ww / 2)
|
|
||||||
wy := (int32(dh) / 2) - (wh / 2)
|
|
||||||
// TODO this needs to be run on uitask!
|
|
||||||
s.setRect(int(wx), int(wy), int(ww), int(wh), 0)
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue