Added horizontal scrollbars to Listboxes on Windows. Also fixed typos and bugs in Windows sysData.selectedTexts().
This commit is contained in:
parent
dcc21eb087
commit
bd1926db17
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue