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:
parent
1d9a883431
commit
165308b819
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue