From 75004dfbe5feb58ee30ae9f136daa08cf3869f6b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 1 May 2009 21:49:43 +0000 Subject: [PATCH] implement changing wxChoice and wxComboBox height git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@60461 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 4 +++ include/wx/msw/choice.h | 17 ++++++++-- src/msw/choice.cpp | 75 +++++++++++++++++++++++++++++++++-------- 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 7d0825aa3b..34fded9b03 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -332,6 +332,10 @@ All (GUI): - wxGrid: add possibility to prevent resizing of individual rows/columns. - wxHTML: add support for table borders width (Laurent Humbertclaude). +MSW: + +- Allow changing the height of wxChoice and wxComboBox. + i18n: - Korean translations added (Sungkee Jung). diff --git a/include/wx/msw/choice.h b/include/wx/msw/choice.h index 4f28ec07c2..e069ec2a48 100644 --- a/include/wx/msw/choice.h +++ b/include/wx/msw/choice.h @@ -92,7 +92,11 @@ protected: virtual wxBorder GetDefaultBorder() const { return wxBORDER_NONE; } // common part of all ctors - void Init() { m_lastAcceptedSelection = wxID_NONE; } + void Init() + { + m_lastAcceptedSelection = wxID_NONE; + m_heightOwn = wxDefaultCoord; + } virtual void DoDeleteOneItem(unsigned int n); virtual void DoClear(); @@ -114,7 +118,10 @@ protected: // update the height of the drop down list to fit the number of items we // have (without changing the visible height) - void UpdateVisibleHeight(); + void MSWUpdateDropDownHeight(); + + // set the height of the visible part of the control to m_heightOwn + void MSWUpdateVisibleHeight(); // create and initialize the control bool CreateAndInit(wxWindow *parent, wxWindowID id, @@ -128,12 +135,18 @@ protected: // free all memory we have (used by Clear() and dtor) void Free(); +#if wxUSE_DEFERRED_SIZING + virtual void MSWEndDeferWindowPos(); +#endif // wxUSE_DEFERRED_SIZING // last "completed" selection, i.e. not the transient one while the user is // browsing the popup list: this is only used when != wxID_NONE which is // the case while the drop down is opened int m_lastAcceptedSelection; + // the height of the control itself if it was set explicitly or + // wxDefaultCoord if it hadn't + int m_heightOwn; DECLARE_DYNAMIC_CLASS_NO_COPY(wxChoice) }; diff --git a/src/msw/choice.cpp b/src/msw/choice.cpp index cf5b4e6ef0..6fc0e4cb3e 100644 --- a/src/msw/choice.cpp +++ b/src/msw/choice.cpp @@ -265,7 +265,7 @@ int wxChoice::DoInsertItems(const wxArrayStringsAdapter& items, // we need to refresh our size in order to have enough space for the // newly added items if ( !IsFrozen() ) - UpdateVisibleHeight(); + MSWUpdateDropDownHeight(); InvalidateBestSize(); @@ -279,7 +279,7 @@ void wxChoice::DoDeleteOneItem(unsigned int n) SendMessage(GetHwnd(), CB_DELETESTRING, n, 0); if ( !IsFrozen() ) - UpdateVisibleHeight(); + MSWUpdateDropDownHeight(); InvalidateBestSize(); } @@ -289,7 +289,7 @@ void wxChoice::DoClear() SendMessage(GetHwnd(), CB_RESETCONTENT, 0, 0); if ( !IsFrozen() ) - UpdateVisibleHeight(); + MSWUpdateDropDownHeight(); InvalidateBestSize(); } @@ -448,13 +448,31 @@ void* wxChoice::DoGetItemClientData(unsigned int n) const } // ---------------------------------------------------------------------------- -// wxMSW specific helpers +// wxMSW-specific geometry management // ---------------------------------------------------------------------------- -void wxChoice::UpdateVisibleHeight() +void wxChoice::MSWUpdateVisibleHeight() +{ + if ( m_heightOwn != wxDefaultCoord ) + ::SendMessage(GetHwnd(), CB_SETITEMHEIGHT, (WPARAM)-1, m_heightOwn); +} + +#if wxUSE_DEFERRED_SIZING +void wxChoice::MSWEndDeferWindowPos() +{ + // we can only set the height of the choice itself now as it is reset to + // default every time the control is resized + MSWUpdateVisibleHeight(); + + wxChoiceBase::MSWEndDeferWindowPos(); +} +#endif // wxUSE_DEFERRED_SIZING + +void wxChoice::MSWUpdateDropDownHeight() { // be careful to not change the width here - DoSetSize(wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, GetSize().y, wxSIZE_USE_EXISTING); + DoSetSize(wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, GetSize().y, + wxSIZE_USE_EXISTING); } void wxChoice::DoMoveWindow(int x, int y, int width, int height) @@ -488,20 +506,28 @@ void wxChoice::DoSetSize(int x, int y, int width, int height, int sizeFlags) { - int heightOrig = height; + const int heightOrig = height; // 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 != wxDefaultCoord ) { - // don't make the drop down list too tall, arbitrarily limit it to 40 - // items max and also don't leave it empty + // 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) + if ( height > UCHAR_MAX ) + height = UCHAR_MAX; + m_heightOwn = height; + + // 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 ( !nItems ) nItems = 9; - else if ( nItems > 24 ) - nItems = 24; + else if ( nItems > 30 ) + nItems = 30; // add space for the drop down list const int hItem = SendMessage(GetHwnd(), CB_GETITEMHEIGHT, 0, 0); @@ -527,10 +553,27 @@ void wxChoice::DoSetSize(int x, int y, wxControl::DoSetSize(x, y, width, height, sizeFlags); - // If we're storing a pending size, make sure we store - // the original size for reporting back to the app. - if (m_pendingSize != wxDefaultSize) + // 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, heightOrig); + } +#else // !wxUSE_DEFERRED_SIZING + // always update the visible height immediately + MSWUpdateVisibleHeight(); +#endif // wxUSE_DEFERRED_SIZING } wxSize wxChoice::DoGetBestSize() const @@ -559,6 +602,10 @@ wxSize wxChoice::DoGetBestSize() const return best; } +// ---------------------------------------------------------------------------- +// MSW message handlers +// ---------------------------------------------------------------------------- + WXLRESULT wxChoice::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { switch ( nMsg ) -- 2.45.2