diff options
| author | Pietro Gagliardi <[email protected]> | 2014-02-24 13:22:59 -0500 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2014-02-24 13:22:59 -0500 |
| commit | 165308b81973d90d023da5254e92c6fa7ae386eb (patch) | |
| tree | c7b728d2791075cd715ccbeca4dedf47ad067394 | |
| parent | 1d9a8834311ffc00bbd6dab1ee64f53f9e634db7 (diff) | |
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).
| -rw-r--r-- | init_windows.go | 4 | ||||
| -rw-r--r-- | prefsize_windows.go | 156 |
2 files changed, 158 insertions, 2 deletions
diff --git a/init_windows.go b/init_windows.go index 5280742..eaf4816 100644 --- a/init_windows.go +++ b/init_windows.go @@ -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 diff --git a/prefsize_windows.go b/prefsize_windows.go new file mode 100644 index 0000000..3ccc781 --- /dev/null +++ b/prefsize_windows.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 +} |
