wxSize wxChoice::DoGetBestSize() const { // find the widest string int wChoice = 0; int hChoice; const unsigned int nItems = GetCount(); for ( unsigned int i = 0; i < nItems; i++ ) { int wLine; GetTextExtent(GetString(i), &wLine, NULL); if ( wLine > wChoice ) wChoice = wLine; } // give it some reasonable default value if there are no strings in the // list if ( wChoice == 0 ) wChoice = 100; // the combobox should be slightly larger than the widest string wChoice += 5*GetCharWidth(); if( HasFlag( wxCB_SIMPLE ) ) { hChoice = SetHeightSimpleComboBox( nItems ); } else hChoice = EDIT_HEIGHT_FROM_CHAR_HEIGHT(GetCharHeight()); wxSize best(wChoice, hChoice); CacheBestSize(best); return best; }
wxSize wxChoice::DoGetSizeFromTextSize(int xlen, int ylen) const { int cHeight = GetCharHeight(); // We are interested in the difference of sizes between the whole control // and its child part. I.e. arrow, separators, etc. wxSize tsize(xlen, 0); // FIXME-VC6: Only VC6 needs this guard, see WINVER definition in // include/wx/msw/wrapwin.h #if defined(WINVER) && WINVER >= 0x0500 WinStruct<COMBOBOXINFO> info; if ( MSWGetComboBoxInfo(&info) ) { tsize.x += info.rcItem.left + info.rcButton.right - info.rcItem.right + info.rcItem.left + 3; // right and extra margins } else // Just use some rough approximation. #endif // WINVER >= 0x0500 { tsize.x += 4*cHeight; } // set height on our own if( HasFlag( wxCB_SIMPLE ) ) tsize.y = SetHeightSimpleComboBox(GetCount()); else tsize.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cHeight); // Perhaps the user wants something different from CharHeight if ( ylen > 0 ) tsize.IncBy(0, ylen - cHeight); return tsize; }
void wxChoice::DoSetSize(int x, int y, int width, int height, int sizeFlags) { const int heightBest = GetBestSize().y; // we need the real height below so get the current one if it's not given if ( height == wxDefaultCoord ) { // height not specified, use the same as before DoGetSize(NULL, &height); } else if ( height == heightBest ) { // we don't need to manually manage our height, let the system use the // default one m_heightOwn = wxDefaultCoord; } else // non-default height specified { // set our new own height but be careful not to make it too big: the // native control apparently stores it as a single byte and so setting // own height to 256 pixels results in default height being used (255 // is still ok) m_heightOwn = height; if ( m_heightOwn > UCHAR_MAX ) m_heightOwn = UCHAR_MAX; // nor too small: see MSWUpdateVisibleHeight() else if ( m_heightOwn < COMBO_HEIGHT_ADJ ) m_heightOwn = COMBO_HEIGHT_ADJ; } // the height which we must pass to Windows should be the total height of // the control including the drop down list while the height given to us // is, of course, just the height of the permanently visible part of it so // add the drop down height to it // don't make the drop down list too tall, arbitrarily limit it to 30 // items max and also don't make it too small if it's currently empty size_t nItems = GetCount(); if (!HasFlag(wxCB_SIMPLE)) { if ( !nItems ) nItems = 9; else if ( nItems > 30 ) nItems = 30; } const int hItem = SendMessage(GetHwnd(), CB_GETITEMHEIGHT, 0, 0); int heightWithItems = 0; if (!HasFlag(wxCB_SIMPLE)) heightWithItems = height + hItem*nItems; else heightWithItems = SetHeightSimpleComboBox(nItems); // do resize the native control wxControl::DoSetSize(x, y, width, heightWithItems, sizeFlags); // make the control itself of the requested height: notice that this // must be done after changing its size or it has no effect (apparently // the height is reset to default during the control layout) and that it's // useless to to do it when using the deferred sizing -- in this case it // will be done from MSWEndDeferWindowPos() #if wxUSE_DEFERRED_SIZING if ( m_pendingSize == wxDefaultSize ) { // not using deferred sizing, update it immediately MSWUpdateVisibleHeight(); } else // in the middle of deferred sizing { // we need to report the size of the visible part of the control back // in GetSize() and not height stored by DoSetSize() in m_pendingSize m_pendingSize = wxSize(width, height); } #else // !wxUSE_DEFERRED_SIZING // always update the visible height immediately MSWUpdateVisibleHeight(); #endif // wxUSE_DEFERRED_SIZING }