Added horizontal scrollbars to Listboxes on Windows. Also fixed typos and bugs in Windows sysData.selectedTexts().

This commit is contained in:
Pietro Gagliardi 2014-04-13 02:57:35 -04:00
parent dcc21eb087
commit bd1926db17
2 changed files with 130 additions and 5 deletions

View File

@ -71,6 +71,7 @@ var stdDlgSizes = [nctypes]dlgunits{
var (
_selectObject = gdi32.NewProc("SelectObject")
_getTextExtentPoint32 = gdi32.NewProc("GetTextExtentPoint32W")
_getTextMetrics = gdi32.NewProc("GetTextMetricsW")
_getWindowDC = user32.NewProc("GetWindowDC")
_releaseDC = user32.NewProc("ReleaseDC")
@ -149,6 +150,127 @@ func muldiv(ma int, mb int, div int) int {
return int(int32(r1))
}
// List Boxes do not dynamically handle horizontal scrollbars.
// We have to manually handle this ourselves.
// TODO make this run on the main thread when we switch to uitask taking function literals
// TODO this is inefficient; some caching would be nice
func recalcListboxWidth(hwnd _HWND) {
var size _SIZE
ret := make(chan uiret)
defer close(ret)
uitask <- &uimsg{
call: _sendMessage,
p: []uintptr{
uintptr(hwnd),
uintptr(_LB_GETCOUNT),
uintptr(0),
uintptr(0),
},
ret: ret,
}
r := <-ret
if r.ret == uintptr(_LB_ERR) { // failure
panic(fmt.Errorf("error getting number of items for Listbox width calculations: %v", r.err))
}
n := int(r.ret)
uitask <- &uimsg{
call: _getWindowDC,
p: []uintptr{uintptr(hwnd)},
ret: ret,
}
r = <-ret
if r.ret == 0 { // failure
panic(fmt.Errorf("error getting DC for Listbox width calculations: %v", r.err))
}
dc := _HANDLE(r.ret)
uitask <- &uimsg{
call: _selectObject,
p: []uintptr{
uintptr(dc),
uintptr(controlFont),
},
ret: ret,
}
r = <-ret
if r.ret == 0 { // failure
panic(fmt.Errorf("error loading control font into device context for Listbox width calculation: %v", r.err))
}
hextent := uintptr(0)
for i := 0; i < n; i++ {
uitask <- &uimsg{
call: _sendMessage,
p: []uintptr{
uintptr(hwnd),
uintptr(_LB_GETTEXTLEN),
uintptr(_WPARAM(i)),
uintptr(0),
},
ret: ret,
}
r := <-ret
if r.ret == uintptr(_LB_ERR) {
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(hwnd),
uintptr(_LB_GETTEXT),
uintptr(_WPARAM(i)),
uintptr(_LPARAM(unsafe.Pointer(&str[0]))),
},
ret: ret,
}
r = <-ret
if r.ret == uintptr(_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)")
}
// r.ret is still the length of the string; this time without the null terminator
uitask <- &uimsg{
call: _getTextExtentPoint32,
p: []uintptr{
uintptr(dc),
uintptr(unsafe.Pointer(&str[0])),
r.ret,
uintptr(unsafe.Pointer(&size)),
},
ret: ret,
}
r = <-ret
if r.ret == 0 { // failure
panic(fmt.Errorf("error getting width of item %d text for Listbox width calculation: %v", i, r.err))
}
if hextent < uintptr(size.cx) {
hextent = uintptr(size.cx)
}
}
uitask <- &uimsg{
call: _releaseDC,
p: []uintptr{
uintptr(hwnd),
uintptr(dc),
},
ret: ret,
}
r = <-ret
if r.ret == 0 { // failure
panic(fmt.Errorf("error releasing DC for Listbox width calculations: %v", r.err))
}
uitask <- &uimsg{
call: _sendMessage,
p: []uintptr{
uintptr(hwnd),
uintptr(_LB_SETHORIZONTALEXTENT),
hextent,
uintptr(0),
},
ret: ret,
}
<-ret
}
type _SIZE struct {
cx int32 // originally LONG
cy int32

View File

@ -91,9 +91,9 @@ var classTypes = [nctypes]*classData{
// we don't use _LBS_STANDARD because it sorts (and has WS_BORDER; see above)
// _LBS_NOINTEGRALHEIGHT gives us exactly the size we want
// TODO say why we don't use LBS_MULTISEL (listbox docs and http://msdn.microsoft.com/en-us/library/windows/desktop/aa511485.aspx)
style: _LBS_NOTIFY | _LBS_NOINTEGRALHEIGHT | _WS_VSCROLL | controlstyle,
style: _LBS_NOTIFY | _LBS_NOINTEGRALHEIGHT | _WS_HSCROLL | _WS_VSCROLL | controlstyle,
xstyle: _WS_EX_CLIENTEDGE | controlxstyle,
altStyle: _LBS_EXTENDEDSEL | _LBS_NOTIFY | _LBS_NOINTEGRALHEIGHT | _WS_VSCROLL | controlstyle,
altStyle: _LBS_EXTENDEDSEL | _LBS_NOTIFY | _LBS_NOINTEGRALHEIGHT | _WS_HSCROLL | _WS_VSCROLL | controlstyle,
appendMsg: _LB_ADDSTRING,
insertBeforeMsg: _LB_INSERTSTRING,
deleteMsg: _LB_DELETESTRING,
@ -355,6 +355,7 @@ func (s *sysData) append(what string) {
} else if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) {
panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", r.err))
}
recalcListboxWidth(s.hwnd)
}
func (s *sysData) insertBefore(what string, index int) {
@ -376,6 +377,7 @@ func (s *sysData) insertBefore(what string, index int) {
} else if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) {
panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", r.err))
}
recalcListboxWidth(s.hwnd)
}
func (s *sysData) selectedIndex() int {
@ -462,7 +464,7 @@ func (s *sysData) selectedTexts() []string {
}
r := <-ret
if r.ret == uintptr(_LB_ERR) {
panic("UI library internal error: LB_ERR from LB_GETTEXTLEN in what we know is a valid listbox index (came from LB_GETSELITEMS")
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{
@ -475,9 +477,9 @@ func (s *sysData) selectedTexts() []string {
},
ret: ret,
}
<-ret
r = <-ret
if r.ret == uintptr(_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")
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)
}
@ -526,6 +528,7 @@ func (s *sysData) delete(index int) {
if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) {
panic(fmt.Errorf("failed to delete item from combobox/listbox (last error: %v)", r.err))
}
recalcListboxWidth(s.hwnd)
}
func (s *sysData) setIndeterminate() {