[Effective WX] 理解wxWindow中的各种size
2012-08-16 22:31
134 查看
在wxWidget中,wxWindow有相当多的size,每种size有各种不同的用途,特别是与wxSize联系起来时,就特别容易混淆。这里从代码的角度来理清各种size。
那几种size就是size, min size, max size, best size, virtual size
首先我们来看wxWindowBase类中几个size的数据成员:
min size/max size相关:
[align=left]上面几个成员变量是关于min size和max size的width/height.[/align]
[align=left]virtual size 相关:[/align]
[align=left]best size相关:[/align]
这个变量是关于best size的。通常best size都是计算出来(后面将会看到),不过有些窗口控件,可以将这个size cache下来,不用重复计算。
[align=left]size相关:[/align]
[align=left]wxWindowBase并没有维护一个关于size的成员,GetSize/SetSize都是直接调用api来获取的。[/align]
[align=left]我们客户端代码调用窗口的SetSize函数就是调用DoSetSize函数。[/align]
[align=left]实际上DoSetSize函数在wxWindowBase中是一个纯虚函数,由任何继承的实际窗口类来重写。[/align]
[align=left]在windows平台上,wxWindowMSW来实现了这个DoSetSize函数:[/align]
可以看到,通常我们调用SetSize都是传入参数wxSIZE_USE_EXISTING,加入我们传入wxDefaultSize,我们不会用DoGetBestSize 函数返回的结果,而只是用currentW/currentH的值。也就是调用GetSize(& currentW ,
¤tH );得到的值。正常情况,通过API来设置改变窗口的大小。
[align=left]有趣的是,这个函数相似地调用DoGetSize函数,也是一个纯虚函数,在wxWindowBase类中。wxWindowMSW重新实现了它。[/align]
[align=left]下面函数中的wxGetWindowRect就是得到整个窗口的size(包括caption, client region, 和border等)。[/align]
[align=left]wxWindow创建过程来跟踪各个size的处理[/align]
[align=left]我们通常创建一个wxWindow时,传入Create或者构造函数中size,可以是wxDefaultSize也可以是一个具体值,这个值将会传入wxWindowMSW中的wxWindowMSW::Create函数,我们来看下这个函数干了些什么事情:[/align]
[align=left]我们关心的2个函数调用就是CreateBase和MSWCreate,前者是基类wxWindowBase的函数,但是这个函数几乎没干什么事情,直接将size忽略掉了。用size参数的是MSWCreate函数。这是个跟windows平台相关的函数。这个函数调用了(void) MSWGetCreateWindowCoords(pos , size, x, y , w, h);。将size传了进去。返回的x/y/w/h,为具体的position和size信息。[/align]
[align=left]WidthDefault/HeightDefault几乎没干什么事情,如果传入值是-1,就直接返回一个固定值为20,否则,原封不动的返回传入的值。所以说,我们通常创建一个窗口时,如果不指定size,那么它就是默认的size (20, 20)。至少从这里看到是这样的。[/align]
[align=left]我们再以wxButton的创建过程来跟踪代码:[/align]
[align=left]wxButton* pBtn = new wxButton(parentWin, wxID_ANY, "button", wxDefaultPosition, wxDefaultSize);[/align]
wxButton构造函数会调用Create函数,传入相应的参数。Create函数会调用父类wxControl的CreateControl函数
[align=left]这个CreateControl几乎不干实际的活,简单的调用wxWindowBase类的CreateBase函数。前面说过CreateBase不看size参数。[/align]
[align=left]所以实际干活的是这一句:[/align]
[align=left]
[align=left]这个是基类wxControl的函数,做了一些关于size的事情如下:[/align]
[align=left]从这里看出,它仅仅是给wxButton一个(1, 1)的最小size。注意,从comment可以看到,此时无法拿到best size,因为还没有创建button control。[/align]
[align=left]然后重要的wxWindowBase类的SetInitialSize函数调用。[/align]
[align=left]注意到SetInitialSize函数内部的注释。首先调用SetMinSize函数,如果用户没有传入Size,比如wxDefaultSize,那么m_minWidth/m_minHeight就会为-1。如果有那么minSize就等于create时传入的值,除非后面再调用SetMinSize进行了更改。[/align]
[align=left]调用GetEffectiveMinSize获取一个best size。之后与GetSize()函数返回的size做比较,不相等,则SetSize到best size。[/align]
[align=left]一旦创建wxButton之后,调用GetSize(调用DoGetSize),是通过hwnd拿到窗口的size。涉及到win32 api。[/align]
[align=left]我们来看下GetEffectiveMinSize做了什么事情:[/align]
[align=left]首先获取minSize,如果有宽度或高度为-1,则要获取best size,因为那个min size就是假的。用best size来更新这个min size。继续看GetBestSize函数:[/align]
[align=left]如果我们之前设置了best size cache,那么就会直接返回这个size。否则就需要调用虚函数DoGetBestSize来获取具体控件/窗口的best size。[/align]
[align=left]注意这个函数是虚函数,并不是纯虚的,所以wxWindowBase提供类个默认实现。我们先来看它的实现:[/align]
[align=left]函数针对不同情况,有不同的处理。[/align]
[align=left]a) 假设窗口有一个sizer,那么获取sizer的minSize。也就是能容纳sizer里面所有子窗口的最小的size,然后加上non-client的sizer,就是窗口期望的best size,因为这样我们就能看到它所含的sizer里面的所有的子窗口。[/align]
GetWindowSizeForVirtualSize函数默认返回传入的参数,对于非scroll window类的窗口来说,都是如此。因为non-scroll window没有virtual size的说法。通常来说,best virtual size就是能够容纳所有的子窗口的size,但是一般client 窗口无法显示这么大的区域,在scroll
window类的窗口中。所以在scroll window类的窗口中,best size就是best virtual size。
[align=left]b) 考虑自身没有sizer,但是有子窗口的情况:[/align]
[align=left]loop所有的子窗口,计算它们的size,overlap所有的窗口矩形,求解最小的fitting window size。[/align]
[align=left]针对这种情况,还需要加上non-client 的size.[/align]
[align=left]c) 最后一种情况,就是没有子窗口,是一个树叶窗口节点。 [/align]
[align=left]首先它获取minsize,如果是个有效的size(width != -1 && height != -1),那么就直接返回它。否则就用GetSize返回的结果。结合上面的GetEffectiveSize函数调用过程,如果我们没有传入size,那么GetEffectivSize函数返回的结果就是窗口创建后给出的size。注意,comment说到,会重新设置minsize到这个最好的size。[/align]
[align=left]针对wxButton,它重新实现了DoGetBestSize函数:[/align]
主要是根据button caption字体进行了计算。GetDefaultSize来做实际的活,主要是一个经验公式。
那几种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;
[align=left]上面几个成员变量是关于min size和max size的width/height.[/align]
[align=left]virtual size 相关:[/align]
// Virtual size (scrolling) wxSize m_virtualSize; int m_minVirtualWidth; // VirtualSizeHints int m_minVirtualHeight; int m_maxVirtualWidth; int m_maxVirtualHeight;
[align=left]best size相关:[/align]
// 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下来,不用重复计算。
[align=left]size相关:[/align]
[align=left]wxWindowBase并没有维护一个关于size的成员,GetSize/SetSize都是直接调用api来获取的。[/align]
[align=left]我们客户端代码调用窗口的SetSize函数就是调用DoSetSize函数。[/align]
// 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); }
[align=left]实际上DoSetSize函数在wxWindowBase中是一个纯虚函数,由任何继承的实际窗口类来重写。[/align]
[align=left]在windows平台上,wxWindowMSW来实现了这个DoSetSize函数:[/align]
// 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 height = currentH ; } } DoMoveWindow( x, y , width, height); }
可以看到,通常我们调用SetSize都是传入参数wxSIZE_USE_EXISTING,加入我们传入wxDefaultSize,我们不会用DoGetBestSize 函数返回的结果,而只是用currentW/currentH的值。也就是调用GetSize(& currentW ,
¤tH );得到的值。正常情况,通过API来设置改变窗口的大小。
[align=left]有趣的是,这个函数相似地调用DoGetSize函数,也是一个纯虚函数,在wxWindowBase类中。wxWindowMSW重新实现了它。[/align]
[align=left]下面函数中的wxGetWindowRect就是得到整个窗口的size(包括caption, client region, 和border等)。[/align]
// Get total size void wxWindowMSW ::DoGetSize( int *x , int * y) const { { RECT rect = wxGetWindowRect( GetHwnd()); if ( x ) * x = rect .right - rect.left ; if ( y ) * y = rect .bottom - rect.top ; } }
[align=left]wxWindow创建过程来跟踪各个size的处理[/align]
[align=left]我们通常创建一个wxWindow时,传入Create或者构造函数中size,可以是wxDefaultSize也可以是一个具体值,这个值将会传入wxWindowMSW中的wxWindowMSW::Create函数,我们来看下这个函数干了些什么事情:[/align]
bool wxWindowMSW ::Create( wxWindow *parent , wxWindowID id , const wxPoint & pos, const wxSize & size, long style , const wxString & name) { wxCHECK_MSG( parent, false , wxT( "can't create wxWindow without parent") ); if ( ! CreateBase(parent , id, pos, size , style, wxDefaultValidator, name ) ) return false ; parent-> AddChild(this ); WXDWORD exstyle; DWORD msflags = MSWGetCreateWindowFlags (&exstyle); #ifdef __WXUNIVERSAL__ // no borders, we draw them ourselves exstyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE | WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE); msflags &= ~WS_BORDER; #endif // wxUniversal if ( IsShown() ) { msflags |= WS_VISIBLE ; } if ( ! MSWCreate(wxCanvasClassName , NULL, pos, size , msflags, exstyle) ) return false ; InheritAttributes(); return true; }
[align=left]我们关心的2个函数调用就是CreateBase和MSWCreate,前者是基类wxWindowBase的函数,但是这个函数几乎没干什么事情,直接将size忽略掉了。用size参数的是MSWCreate函数。这是个跟windows平台相关的函数。这个函数调用了(void) MSWGetCreateWindowCoords(pos , size, x, y , w, h);。将size传了进去。返回的x/y/w/h,为具体的position和size信息。[/align]
if ( size.x == wxDefaultCoord || size.y == wxDefaultCoord) { nonDefault = true ; } w = WidthDefault(size .x); h = HeightDefault(size .y);
[align=left]WidthDefault/HeightDefault几乎没干什么事情,如果传入值是-1,就直接返回一个固定值为20,否则,原封不动的返回传入的值。所以说,我们通常创建一个窗口时,如果不指定size,那么它就是默认的size (20, 20)。至少从这里看到是这样的。[/align]
[align=left]我们再以wxButton的创建过程来跟踪代码:[/align]
[align=left]wxButton* pBtn = new wxButton(parentWin, wxID_ANY, "button", wxDefaultPosition, wxDefaultSize);[/align]
wxButton构造函数会调用Create函数,传入相应的参数。Create函数会调用父类wxControl的CreateControl函数
if ( ! CreateControl (parent , id, pos , size , style, validator , name ) ) return false ;
[align=left]这个CreateControl几乎不干实际的活,简单的调用wxWindowBase类的CreateBase函数。前面说过CreateBase不看size参数。[/align]
[align=left]所以实际干活的是这一句:[/align]
[align=left]
return MSWCreateControl ( _T( "BUTTON" ), msStyle , pos, size , label , exstyle );[/align]
[align=left]这个是基类wxControl的函数,做了一些关于size的事情如下:[/align]
// choose the position for the control: we have a problem with default size // here as we can't calculate the best size before the control exists // (DoGetBestSize() may need to use m_hWnd), so just choose the minimal // possible but non 0 size because 0 window width/height result in problems // elsewhere int x = pos . x == wxDefaultCoord ? 0 : pos . x, y = pos . y == wxDefaultCoord ? 0 : pos . y, w = size . x == wxDefaultCoord ? 1 : size . x, h = size . y == wxDefaultCoord ? 1 : size . y; ... SetInitialSize(size);
[align=left]从这里看出,它仅仅是给wxButton一个(1, 1)的最小size。注意,从comment可以看到,此时无法拿到best size,因为还没有创建button control。[/align]
[align=left]然后重要的wxWindowBase类的SetInitialSize函数调用。[/align]
void wxWindowBase :: SetInitialSize( const wxSize & size) { // Set the min size to the size passed in. This will usually either be // wxDefaultSize or the size passed to this window's ctor/Create function. SetMinSize( size ); // Merge the size with the best size if needed wxSize best = GetEffectiveMinSize (); // If the current size doesn't match then change it if ( GetSize () != best ) SetSize (best ); }
// Call these to override what GetBestSize() returns. This // method is only virtual because it is overriden in wxTLW // as a different API for SetSizeHints(). virtual void SetMinSize ( const wxSize & minSize ) { m_minWidth = minSize .x ; m_minHeight = minSize .y ; } virtual void SetMaxSize ( const wxSize & maxSize ) { m_maxWidth = maxSize .x ; m_maxHeight = maxSize .y ; } // Override these methods to impose restrictions on min/max size. // The easier way is to call SetMinSize() and SetMaxSize() which // will have the same effect. Doing both is non-sense. virtual wxSize GetMinSize () const { return wxSize ( m_minWidth, m_minHeight ); } virtual wxSize GetMaxSize () const { return wxSize ( m_maxWidth, m_maxHeight ); }
[align=left]注意到SetInitialSize函数内部的注释。首先调用SetMinSize函数,如果用户没有传入Size,比如wxDefaultSize,那么m_minWidth/m_minHeight就会为-1。如果有那么minSize就等于create时传入的值,除非后面再调用SetMinSize进行了更改。[/align]
[align=left]调用GetEffectiveMinSize获取一个best size。之后与GetSize()函数返回的size做比较,不相等,则SetSize到best size。[/align]
[align=left]一旦创建wxButton之后,调用GetSize(调用DoGetSize),是通过hwnd拿到窗口的size。涉及到win32 api。[/align]
[align=left]我们来看下GetEffectiveMinSize做了什么事情:[/align]
wxSize wxWindowBase :: GetEffectiveMinSize() const { // merge the best size with the min size, giving priority to the min size wxSize min = GetMinSize (); if ( min .x == wxDefaultCoord || min .y == wxDefaultCoord) { wxSize best = GetBestSize(); if (min . x == wxDefaultCoord ) min . x = best .x ; if (min . y == wxDefaultCoord ) min . y = best .y ; } return min ; }
[align=left]首先获取minSize,如果有宽度或高度为-1,则要获取best size,因为那个min size就是假的。用best size来更新这个min size。继续看GetBestSize函数:[/align]
// get the size best suited for the window (in fact, minimal // acceptable size using which it will still look "nice" in // most situations) wxSize GetBestSize () const { if (m_bestSizeCache . IsFullySpecified()) return m_bestSizeCache ; return DoGetBestSize (); }
[align=left]如果我们之前设置了best size cache,那么就会直接返回这个size。否则就需要调用虚函数DoGetBestSize来获取具体控件/窗口的best size。[/align]
// get the size which best suits the window: for a control, it would be // the minimal size which doesn't truncate the control, for a panel - the // same size as it would have after a call to Fit() virtual wxSize DoGetBestSize () const;
[align=left]注意这个函数是虚函数,并不是纯虚的,所以wxWindowBase提供类个默认实现。我们先来看它的实现:[/align]
// return the size best suited for the current window wxSize wxWindowBase :: DoGetBestSize() const { wxSize best ; if ( m_windowSizer ) { // Adjust to window size, since the return value of GetWindowSizeForVirtualSize is // expressed in window and not client size wxSize minSize = m_windowSizer-> GetMinSize (); wxSize size ( GetSize()); wxSize clientSize ( GetClientSize()); wxSize minWindowSize ( minSize. x + size . x - clientSize .x , minSize .y + size. y - clientSize . y); best = GetWindowSizeForVirtualSize ( minWindowSize); return best ; } else if ( !GetChildren (). empty() #ifdef __WXMAC__ && wxHasRealChildren(this) #endif ) { // our minimal acceptable size is such that all our visible child // windows fit inside int maxX = 0, maxY = 0; for ( wxWindowList :: compatibility_iterator node = GetChildren ().GetFirst (); node ; node = node -> GetNext() ) { wxWindow *win = node-> GetData (); if ( win -> IsTopLevel() || ! win ->IsShown () #if wxUSE_STATUSBAR || wxDynamicCast (win , wxStatusBar) #endif // wxUSE_STATUSBAR ) { // dialogs and frames lie in different top level windows - // don't deal with them here; as for the status bars, they // don't lie in the client area at all continue ; } int wx , wy, ww , wh ; win ->GetPosition (& wx, & wy ); // if the window hadn't been positioned yet, assume that it is in // the origin if ( wx == wxDefaultCoord ) wx = 0; if ( wy == wxDefaultCoord ) wy = 0; win ->GetSize (& ww, & wh ); if ( wx + ww > maxX ) maxX = wx + ww; if ( wy + wh > maxY ) maxY = wy + wh; } best = wxSize ( maxX, maxY ); } else // ! has children { // for a generic window there is no natural best size so, if the // minimal size is not set, use the current size but take care to // remember it as minimal size for the next time because our best size // should be constant: otherwise we could get into a situation when the // window is initially at some size, then expanded to a larger size and // then, when the containing window is shrunk back (because our initial // best size had been used for computing the parent min size), we can't // be shrunk back any more because our best size is now bigger wxSize size = GetMinSize(); if ( !size . IsFullySpecified() ) { size .SetDefaults ( GetSize()); wxConstCast (this , wxWindowBase)-> SetMinSize (size ); } // return as-is, unadjusted by the client size difference. return size ; } // Add any difference between size and client size wxSize diff = GetSize () - GetClientSize(); best. x += wxMax (0, diff. x ); best. y += wxMax (0, diff. y ); return best ; }
[align=left]函数针对不同情况,有不同的处理。[/align]
[align=left]a) 假设窗口有一个sizer,那么获取sizer的minSize。也就是能容纳sizer里面所有子窗口的最小的size,然后加上non-client的sizer,就是窗口期望的best size,因为这样我们就能看到它所含的sizer里面的所有的子窗口。[/align]
// Adjust to window size, since the return value of GetWindowSizeForVirtualSize is // expressed in window and not client size wxSize minSize = m_windowSizer-> GetMinSize (); wxSize size ( GetSize()); wxSize clientSize ( GetClientSize()); wxSize minWindowSize ( minSize. x + size . x - clientSize .x , minSize .y + size. y - clientSize . y); best = GetWindowSizeForVirtualSize ( minWindowSize); return best ;
GetWindowSizeForVirtualSize函数默认返回传入的参数,对于非scroll window类的窗口来说,都是如此。因为non-scroll window没有virtual size的说法。通常来说,best virtual size就是能够容纳所有的子窗口的size,但是一般client 窗口无法显示这么大的区域,在scroll
window类的窗口中。所以在scroll window类的窗口中,best size就是best virtual size。
[align=left]b) 考虑自身没有sizer,但是有子窗口的情况:[/align]
win ->GetSize (& ww, & wh ); if ( wx + ww > maxX ) maxX = wx + ww; if ( wy + wh > maxY ) maxY = wy + wh; } best = wxSize ( maxX, maxY );
[align=left]loop所有的子窗口,计算它们的size,overlap所有的窗口矩形,求解最小的fitting window size。[/align]
[align=left]针对这种情况,还需要加上non-client 的size.[/align]
// Add any difference between size and client size wxSize diff = GetSize () - GetClientSize(); best. x += wxMax (0, diff. x ); best. y += wxMax (0, diff. y );
[align=left]c) 最后一种情况,就是没有子窗口,是一个树叶窗口节点。 [/align]
// for a generic window there is no natural best size so, if the // minimal size is not set, use the current size but take care to // remember it as minimal size for the next time because our best size // should be constant: otherwise we could get into a situation when the // window is initially at some size, then expanded to a larger size and // then, when the containing window is shrunk back (because our initial // best size had been used for computing the parent min size), we can't // be shrunk back any more because our best size is now bigger wxSize size = GetMinSize(); if ( !size . IsFullySpecified() ) { size .SetDefaults ( GetSize()); wxConstCast (this , wxWindowBase)-> SetMinSize (size ); } // return as-is, unadjusted by the client size difference. return size ;
[align=left]首先它获取minsize,如果是个有效的size(width != -1 && height != -1),那么就直接返回它。否则就用GetSize返回的结果。结合上面的GetEffectiveSize函数调用过程,如果我们没有传入size,那么GetEffectivSize函数返回的结果就是窗口创建后给出的size。注意,comment说到,会重新设置minsize到这个最好的size。[/align]
[align=left]针对wxButton,它重新实现了DoGetBestSize函数:[/align]
wxSize wxButton :: DoGetBestSize() const { wxClientDC dc (wx_const_cast ( wxButton *, this )); dc. SetFont (GetFont ()); wxCoord wBtn , hBtn ; dc. GetMultiLineTextExtent (GetLabelText (), & wBtn, & hBtn ); // add a margin -- the button is wider than just its label wBtn += 3* GetCharWidth (); hBtn = BUTTON_HEIGHT_FROM_CHAR_HEIGHT (hBtn ); // all buttons have at least the standard size unless the user explicitly // wants them to be of smaller size and used wxBU_EXACTFIT style when // creating the button if ( ! HasFlag (wxBU_EXACTFIT ) ) { wxSize sz = GetDefaultSize(); if (wBtn > sz. x ) sz .x = wBtn; if (hBtn > sz. y ) sz .y = hBtn; return sz ; } wxSize best (wBtn , hBtn); CacheBestSize( best ); return best ; }
主要是根据button caption字体进行了计算。GetDefaultSize来做实际的活,主要是一个经验公式。
wxSize wxButtonBase::GetDefaultSize() { static wxSize s_sizeBtn; if ( s_sizeBtn.x == 0 ) { wxScreenDC dc; dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); // the size of a standard button in the dialog units is 50x14, // translate this to pixels // NB1: the multipliers come from the Windows convention // NB2: the extra +1/+2 were needed to get the size be the same as the // size of the buttons in the standard dialog - I don't know how // this happens, but on my system this size is 75x23 in pixels and // 23*8 isn't even divisible by 14... Would be nice to understand // why these constants are needed though! s_sizeBtn.x = (50 * (dc.GetCharWidth() + 1))/4; s_sizeBtn.y = ((14 * dc.GetCharHeight()) + 2)/8; } return s_sizeBtn; }
相关文章推荐
- [Effective WX] 理解wxWindow中增加和去除/销毁子窗口的过程
- [Effective WX] 理解wxWindow与wxSizer的关系
- 使用大图+脚本,生成各种size的app icon和图片素材
- 对交换机VLAN及各种端口类型的理解
- 算法大全--各种理解
- 一张图彻底理解SQL中的各种join
- OpenCL的NDRange中globalSize,globalSize参数理解及调试笔记
- More Effective C++ ——08_理解各种不同含义的new和delete
- 大话设计模式阅读(1) UML类图各种关系与代码的对应理解
- 理解可执行程序的各种神器
- 关于各种编码的简要理解
- 【深入理解Java虚拟机】之自己编译JDK(已经完成,其中有自己遇到的各种问题及解决办法)
- 通过“中文”两个字来深度剖析各种不同的编码方式,彻底理解乱码是如何产生的?
- 理解ThreadPoolExecutor源码(一)线程池的corePoolSize、maximumPoolSize和poolSize
- 一句话理解神经网络里的batch_size,iterations,epoch
- 深入理解spring中的各种注解
- JAVA程序运行原理:各种配置 环境变量 jdk jre classpath 深入理解!~Myself
- 八 理解各种不同含义的new和delete
- jQuery窗口、文档各种高度的理解
- 关于各种输入输出流的二次理解总结 ,以及输入的三种方法总结。