在wxWidget中,wxWindow有相当多的size,每种size有各种不同的用途,特别是与wxSize联系起来时,就特别容易混淆。这里从代码的角度来理清各种size。
那几种size就是size, min size, max size, best size, virtual size
首先我们来看wxWindowBase类中几个size的数据成员:
min size/max size相关:
// the minimal allowed size for the window (no minimal size if variable(s)
// contain(s) wxDefaultCoord)
int m_minWidth,
m_minHeight,
m_maxWidth,
m_maxHeight;
上面几个成员变量是关于min size和max size的width/height.
virtual size 相关:
// Virtual size (scrolling)
wxSize m_virtualSize;
int m_minVirtualWidth; // VirtualSizeHints
int m_minVirtualHeight;
int m_maxVirtualWidth;
int m_maxVirtualHeight;
best size相关:
// Used to save the results of DoGetBestSize so it doesn't need to be
// recalculated each time the value is needed.
wxSize m_bestSizeCache;
这个变量是关于best size的。通常best size都是计算出来(后面将会看到),不过有些窗口控件,可以将这个size cache下来,不用重复计算。
size相关:
wxWindowBase并没有维护一个关于size的成员,GetSize/SetSize都是直接调用api来获取的。
我们客户端代码调用窗口的SetSize函数就是调用DoSetSize函数。
// set the window size and/or position
void SetSize( int x, int y , int width, int height,
int sizeFlags = wxSIZE_AUTO )
{ DoSetSize(x , y, width, height , sizeFlags); }
void SetSize( int width, int height )
{ DoSetSize( wxDefaultCoord , wxDefaultCoord, width, height , wxSIZE_USE_EXISTING ); }
void SetSize( const wxSize& size )
{ SetSize( size .x, size.y ); }
void SetSize(const wxRect& rect, int sizeFlags = wxSIZE_AUTO)
{ DoSetSize(rect .x, rect.y , rect. width, rect .height, sizeFlags); }
实际上DoSetSize函数在wxWindowBase中是一个纯虚函数,由任何继承的实际窗口类来重写。
在windows平台上,wxWindowMSW来实现了这个DoSetSize函数:
// set the size of the window: if the dimensions are positive, just use them,
// but if any of them is equal to -1, it means that we must find the value for
// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
// which case -1 is a valid value for x and y)
//
// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
// the width/height to best suit our contents, otherwise we reuse the current
// width/height
void wxWindowMSW ::DoSetSize( int x , int y, int width, int height , int sizeFlags)
{
// get the current size and position...
int currentX, currentY ;
int currentW, currentH ;
GetPosition(& currentX, ¤tY );
GetSize(& currentW, ¤tH );
// ... and don't do anything (avoiding flicker) if it's already ok unless
// we're forced to resize the window
if ( x == currentX && y == currentY &&
width == currentW && height == currentH &&
!( sizeFlags & wxSIZE_FORCE ) )
{
return;
}
if ( x == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
x = currentX ;
if ( y == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
y = currentY ;
AdjustForParentClientOrigin( x, y , sizeFlags);
wxSize size = wxDefaultSize ;
if ( width == wxDefaultCoord )
{
if ( sizeFlags & wxSIZE_AUTO_WIDTH )
{
size = DoGetBestSize ();
width = size .x;
}
else
{
// just take the current one
width = currentW ;
}
}
if ( height == wxDefaultCoord )
{
if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
{
if ( size .x == wxDefaultCoord )
{
size = DoGetBestSize ();
}
//else: already called DoGetBestSize() above
height = size .y;
}
else
{
// just take the current one