Added Windows preferred size code. It doesn't work right now; both GetDC() and GetWindowDC() are not returning at all on both wine and Windows XP; need to debug (print guards are included).

This commit is contained in:
Pietro Gagliardi 2014-02-24 13:22:59 -05:00
parent 1d9a883431
commit 165308b819
2 changed files with 158 additions and 2 deletions

View File

@ -66,9 +66,9 @@ func doWindowsInit() (err error) {
if err != nil {
return fmt.Errorf("error initializing standard window class auxiliary info: %v", err)
}
err = getStandardWindowsFonts()
err = getStandardWindowFonts()
if err != nil {
return fmt.Errorf("error getting standard Windows fonts: %v", err)
return fmt.Errorf("error getting standard window fonts: %v", err)
}
// TODO others
return nil // all ready to go

156
prefsize_windows.go Normal file
View File

@ -0,0 +1,156 @@
// 24 february 2014
package ui
import (
// "syscall"
"unsafe"
)
// For Windows, Microsoft just hands you a list of preferred control sizes as part of the MSDN documentation and tells you to roll with it.
// These sizes are given in "dialog units", which are independent of the font in use.
// We need to convert these into standard pixels, which requires we get the device context of the OS window.
// References:
// - http://msdn.microsoft.com/en-us/library/windows/desktop/aa511279.aspx#controlsizing for control sizes
// - http://msdn.microsoft.com/en-us/library/ms645502%28VS.85%29.aspx - the calculation needed
// - http://support.microsoft.com/kb/125681 - to get the base X and Y
// As we are left with incomplete data, an arbitrary size will be chosen
const (
defaultWidth = 100 // 2 * preferred width of buttons
)
type dlgunits struct {
width int
height int
longest bool // TODO actually use this
}
var stdDlgSizes = [nctypes]dlgunits{
c_button: dlgunits{
width: 50,
height: 14,
},
c_checkbox: dlgunits{
// widtdh is not defined here so assume longest
longest: true,
height: 10,
},
c_combobox: dlgunits{
longest: true,
height: 14,
},
c_lineedit: dlgunits{
longest: true,
height: 14,
},
c_label: dlgunits{
longest: true,
height: 8,
},
c_listbox: dlgunits{
longest: true,
// height is not clearly defined here ("an integral number of items (3 items minimum)") so just use a three-line edit control
height: 14 + 10 + 10,
},
}
var (
_getTextMetrics = user32.NewProc("GetTextMetricsW")
_getWindowDC = user32.NewProc("GetWindowDC")
_releaseDC = user32.NewProc("ReleaseDC")
)
func (s *sysData) preferredSize() (width int, height int) {
println("size of control", s.ctype)
var dc _HANDLE
var tm _TEXTMETRICS
var baseX, baseY int
ret := make(chan uiret)
defer close(ret)
println("calling getWindowDC")
uitask <- &uimsg{
call: _getWindowDC,
p: []uintptr{uintptr(s.hwnd)},
ret: ret,
}
r := <-ret
println("getWindowDC",r.ret,r.err)
if r.ret == 0 { // failure
panic(r.err) // TODO return it instead
}
dc = _HANDLE(r.ret)
println("getTextMetrics")
uitask <- &uimsg{
call: _getTextMetrics,
p: []uintptr{
uintptr(dc),
uintptr(unsafe.Pointer(&tm)),
},
ret: ret,
}
r = <-ret
println("getTextMetrics",r.ret,r.err)
if r.ret == 0 { // failure
panic(r.err) // TODO return it instead
}
baseX = int(tm.tmAveCharWidth) // TODO not optimal; third reference has better way
baseY = int(tm.tmHeight)
println("releaseDC")
uitask <- &uimsg{
call: _releaseDC,
p: []uintptr{
uintptr(s.hwnd),
uintptr(dc),
},
ret: ret,
}
r = <-ret
println("releaseDC",r.ret,r.err)
if r.ret == 0 { // failure
panic(r.err) // TODO return it instead
}
// now that we have the conversion factors...
width = stdDlgSizes[s.ctype].width
if width == 0 {
width = defaultWidth
}
height = stdDlgSizes[s.ctype].height
width = muldiv(width, baseX, 4) // equivalent to right of rect
height = muldiv(height, baseY, 8) // equivalent to bottom of rect
println("result:", width, height)
return width, height
}
// attempts to mimic the behavior of kernel32.MulDiv()
// caling it directly would be better (TODO)
// alternatively TODO make sure the rounding is correct
func muldiv(ma int, mb int, div int) int {
xa := int64(ma) * int64(mb)
xa /= int64(div)
return int(xa)
}
type _TEXTMETRICS struct {
tmHeight int32
tmAscent int32
tmDescent int32
tmInternalLeading int32
tmExternalLeading int32
tmAveCharWidth int32
tmMaxCharWidth int32
tmWeight int32
tmOverhang int32
tmDigitizedAspectX int32
tmDigitizedAspectY int32
tmFirstChar uint16
tmLastChar uint16
tmDefaultChar uint16
tmBreakChar uint16
tmItalic byte
tmUnderlined byte
tmStruckOut byte
tmPitchAndFamily byte
tmCharSet byte
}