2014-08-04 19:04:16 -05:00
// 4 august 2014
package ui
import (
"fmt"
"syscall"
)
// #include "winapi_windows.h"
import "C"
type container struct {
2014-10-18 16:03:07 -05:00
* controlSingleHWND
2014-08-04 19:04:16 -05:00
}
type sizing struct {
sizingbase
// for size calculations
2014-10-02 09:05:53 -05:00
baseX C . int
baseY C . int
internalLeading C . LONG // for Label; see Label.commitResize() for details
2014-08-04 19:04:16 -05:00
// for the actual resizing
// possibly the HDWP
}
func makeContainerWindowClass ( ) error {
var errmsg * C . char
err := C . makeContainerWindowClass ( & errmsg )
if err != 0 || errmsg != nil {
return fmt . Errorf ( "%s: %v" , C . GoString ( errmsg ) , syscall . Errno ( err ) )
}
return nil
}
2014-10-18 16:03:07 -05:00
func newContainer ( ) * container {
// don't set preferredSize(); it should never be called
return & container {
controlSingleHWND : newControlSingleHWND ( C . newContainer ( ) ) ,
2014-08-04 19:04:16 -05:00
}
2014-08-04 20:27:35 -05:00
}
2014-10-18 16:03:07 -05:00
// TODO merge with controlSingleHWND
2014-08-04 20:33:58 -05:00
func ( c * container ) show ( ) {
C . ShowWindow ( c . hwnd , C . SW_SHOW )
}
2014-10-18 16:03:07 -05:00
// TODO merge with controlSingleHWND
2014-08-04 20:33:58 -05:00
func ( c * container ) hide ( ) {
C . ShowWindow ( c . hwnd , C . SW_HIDE )
}
2014-10-18 16:03:07 -05:00
func ( c * container ) parent ( ) * controlParent {
return & controlParent { c . hwnd }
2014-08-04 19:04:16 -05:00
}
2014-10-18 16:03:07 -05:00
func ( c * container ) bounds ( d * sizing ) ( int , int , int , int ) {
r := C . containerBounds ( c . hwnd )
return int ( r . left ) , int ( r . top ) , int ( r . right - r . left ) , int ( r . bottom - r . top )
2014-08-04 19:04:16 -05:00
}
// 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/ms645502%28VS.85%29.aspx - the calculation needed
// - http://support.microsoft.com/kb/125681 - to get the base X and Y
// (thanks to http://stackoverflow.com/questions/58620/default-button-size)
2014-08-12 12:10:30 -05:00
// In my tests (see https://github.com/andlabs/windlgunits), the GetTextExtentPoint32() option for getting the base X produces much more accurate results than the tmAveCharWidth option when tested against the sample values given in http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing, but can be off by a pixel in either direction (probably due to rounding errors).
2014-08-04 19:04:16 -05:00
// note on MulDiv():
// div will not be 0 in the usages below
// we also ignore overflow; that isn't likely to happen for our use case anytime soon
func fromdlgunitsX ( du int , d * sizing ) int {
return int ( C . MulDiv ( C . int ( du ) , d . baseX , 4 ) )
}
func fromdlgunitsY ( du int , d * sizing ) int {
return int ( C . MulDiv ( C . int ( du ) , d . baseY , 8 ) )
}
const (
2014-10-18 16:03:07 -05:00
// shared by multiple containers
2014-10-02 09:05:53 -05:00
marginDialogUnits = 7
2014-08-04 19:04:16 -05:00
paddingDialogUnits = 4
)
2014-10-18 16:03:07 -05:00
func ( w * window ) beginResize ( ) ( d * sizing ) {
2014-08-04 19:10:23 -05:00
var baseX , baseY C . int
2014-08-08 22:47:06 -05:00
var internalLeading C . LONG
2014-08-04 19:10:23 -05:00
2014-08-04 19:04:16 -05:00
d = new ( sizing )
2014-10-18 16:03:07 -05:00
C . calculateBaseUnits ( w . hwnd , & baseX , & baseY , & internalLeading )
2014-08-04 19:10:23 -05:00
d . baseX = baseX
d . baseY = baseY
2014-08-08 22:47:06 -05:00
d . internalLeading = internalLeading
2014-08-04 19:04:16 -05:00
2014-10-18 16:03:07 -05:00
d . xpadding = fromdlgunitsX ( paddingDialogUnits , d )
d . ypadding = fromdlgunitsY ( paddingDialogUnits , d )
2014-08-04 19:04:16 -05:00
return d
}
2014-10-18 16:03:07 -05:00
func marginRectDLU ( r * C . RECT , top int , bottom int , left int , right int , d * sizing ) {
r . left += C . LONG ( fromdlgunitsX ( left , d ) )
r . top += C . LONG ( fromdlgunitsY ( top , d ) )
r . right -= C . LONG ( fromdlgunitsX ( right , d ) )
r . bottom -= C . LONG ( fromdlgunitsY ( bottom , d ) )
2014-08-04 19:04:16 -05:00
}