From d99957b6b044289a6fb3872ff9a25ef6d40e574d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 7 Feb 2004 18:42:56 +0000 Subject: [PATCH] multiple fixes to wxChoice/wxCombobox height getting/setting (replaces patches 888171, 834099; fixes bug 880590) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@25574 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 3 ++ include/wx/msw/choice.h | 4 +++ src/msw/choice.cpp | 80 +++++++++++++++++++++++++++++------------ 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 7554eb47e5..2d613b9056 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -35,6 +35,9 @@ INCOMPATIBLE CHANGES SINCE 2.4.x (when WXWIN_COMPATIBILITY_2_4 == 0) - wxID_SEPARATOR (id used for the menu separators) value changed from -1 to -2 - wxGetNumberFromUser() is now in separate wx/numdlg.h, not wx/textdlg.h +- wxChoice and wxCombobox now handle their size in the same way as in all the + other ports under MSW, new code is actually correct but different from weird + stuff they were doing before so the behaviour of your programs might change DEPRECATED METHODS SINCE 2.4.x diff --git a/include/wx/msw/choice.h b/include/wx/msw/choice.h index ab7016061f..ce9d5b58e2 100644 --- a/include/wx/msw/choice.h +++ b/include/wx/msw/choice.h @@ -96,10 +96,14 @@ protected: // MSW implementation virtual wxSize DoGetBestSize() const; + virtual void DoGetSize(int *w, int *h) const; virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); + // get the real height of the control + int GetVisibleHeight() const; + // free all memory we have (used by Clear() and dtor) void Free(); diff --git a/src/msw/choice.cpp b/src/msw/choice.cpp index 220f7c8cfd..4d1df2c1a4 100644 --- a/src/msw/choice.cpp +++ b/src/msw/choice.cpp @@ -118,7 +118,7 @@ bool wxChoice::Create(wxWindow *parent, if ( !CreateControl(parent, id, pos, size, style, validator, name) ) return FALSE; - long msStyle = WS_CHILD | CBS_DROPDOWNLIST | WS_TABSTOP | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL /* | WS_CLIPSIBLINGS */; + long msStyle = WS_CHILD | CBS_DROPDOWNLIST | WS_TABSTOP | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL; if ( style & wxCB_SORT ) msStyle |= CBS_SORT; @@ -367,6 +367,11 @@ wxClientData* wxChoice::DoGetItemClientObject( int n ) const // wxMSW specific helpers // ---------------------------------------------------------------------------- +int wxChoice::GetVisibleHeight() const +{ + return ::SendMessage(GetHwnd(), CB_GETITEMHEIGHT, (WPARAM)-1, 0); +} + void wxChoice::DoMoveWindow(int x, int y, int width, int height) { // here is why this is necessary: if the width is negative, the combobox @@ -385,29 +390,65 @@ void wxChoice::DoMoveWindow(int x, int y, int width, int height) wxControl::DoMoveWindow(x, y, width, height); } +void wxChoice::DoGetSize(int *w, int *h) const +{ + wxControl::DoGetSize(w, h); + + // we need to return only the height of the visible part, not the entire + // height in the Windows sense which includes the height of the drop down + // list as well + if ( h ) + *h = GetVisibleHeight(); +} + void wxChoice::DoSetSize(int x, int y, - int width, int WXUNUSED(height), + int width, int height, int sizeFlags) { - // Ignore height parameter because height doesn't mean 'initially - // displayed' height, it refers to the drop-down menu as well. The - // wxWindows interpretation is different; also, getting the size returns - // the _displayed_ size (NOT the drop down menu size) so - // setting-getting-setting size would not work. + int heightOrig = height; - wxControl::DoSetSize(x, y, width, -1, sizeFlags); + // 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 + if ( height != -1 ) + { + // don't make the drop down list too tall, arbitrarily limit it to 40 + // items max and also don't leave it empty + size_t nItems = GetCount(); + if ( !nItems ) + nItems = 9; + else if ( nItems > 39 ) + nItems = 39; + + // add space for the drop down list + const int hItem = SendMessage(GetHwnd(), CB_GETITEMHEIGHT, 0, 0); + height += hItem*(nItems + 1); + } + + wxControl::DoSetSize(x, y, width, height, sizeFlags); + + // if the height specified for the visible part of the control is + // different from the current one, we need to change it separately + // as it is not affected by normal WM_SETSIZE + if ( height != -1 ) + { + const int hVisibleCurrent = GetVisibleHeight(); + if ( hVisibleCurrent != heightOrig ) + { + SendMessage(GetHwnd(), CB_SETITEMHEIGHT, (WPARAM)-1, heightOrig); + } + } } wxSize wxChoice::DoGetBestSize() const { // find the widest string - int wLine; int wChoice = 0; - int nItems = GetCount(); - for ( int i = 0; i < nItems; i++ ) + const size_t nItems = GetCount(); + for ( size_t i = 0; i < nItems; i++ ) { - wxString str(GetString(i)); - GetTextExtent(str, &wLine, NULL); + int wLine; + GetTextExtent(GetString(i), &wLine, NULL); if ( wLine > wChoice ) wChoice = wLine; } @@ -417,17 +458,10 @@ wxSize wxChoice::DoGetBestSize() const if ( wChoice == 0 ) wChoice = 100; - // the combobox should be larger than the widest string - int cx, cy; - wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); - - wChoice += 5*cx; - - // Choice drop-down list depends on number of items (limited to 10) - size_t nStrings = nItems == 0 ? 10 : wxMin(10, nItems) + 1; - int hChoice = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)*nStrings; + // the combobox should be slightly larger than the widest string + wChoice += 5*GetCharWidth(); - return wxSize(wChoice, hChoice); + return wxSize(wChoice, GetVisibleHeight()); } long wxChoice::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) -- 2.45.2