#if wxUSE_CHOICE && !(defined(__SMARTPHONE__) && defined(__WXWINCE__))
+#include "wx/choice.h"
+
#ifndef WX_PRECOMP
- #include "wx/choice.h"
#include "wx/utils.h"
#include "wx/log.h"
#include "wx/brush.h"
return n;
}
-int wxChoice::DoInsert(const wxString& item, int pos)
+int wxChoice::DoInsert(const wxString& item, unsigned int pos)
{
wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list"));
- wxCHECK_MSG((pos>=0) && (pos<=GetCount()), -1, wxT("invalid index"));
+ wxCHECK_MSG(IsValidInsert(pos), -1, wxT("invalid index"));
int n = (int)SendMessage(GetHwnd(), CB_INSERTSTRING, pos, (LPARAM)item.c_str());
if ( n == CB_ERR )
return n;
}
-void wxChoice::Delete(int n)
+void wxChoice::Delete(unsigned int n)
{
- wxCHECK_RET( n < GetCount(), wxT("invalid item index in wxChoice::Delete") );
+ wxCHECK_RET( IsValid(n), wxT("invalid item index in wxChoice::Delete") );
if ( HasClientObjectData() )
{
{
if ( HasClientObjectData() )
{
- size_t count = GetCount();
- for ( size_t n = 0; n < count; n++ )
+ unsigned int count = GetCount();
+ for ( unsigned int n = 0; n < count; n++ )
{
delete GetClientObject(n);
}
// string list functions
// ----------------------------------------------------------------------------
-int wxChoice::GetCount() const
+unsigned int wxChoice::GetCount() const
{
- return (int)SendMessage(GetHwnd(), CB_GETCOUNT, 0, 0);
+ return (unsigned int)SendMessage(GetHwnd(), CB_GETCOUNT, 0, 0);
}
int wxChoice::FindString(const wxString& s, bool bCase) const
#if defined(__WATCOMC__) && defined(__WIN386__)
// For some reason, Watcom in WIN386 mode crashes in the CB_FINDSTRINGEXACT message.
// wxChoice::Do it the long way instead.
- int count = GetCount();
- for ( int i = 0; i < count; i++ )
+ unsigned int count = GetCount();
+ for ( unsigned int i = 0; i < count; i++ )
{
// as CB_FINDSTRINGEXACT is case insensitive, be case insensitive too
- if ( GetString(i).IsSameAs(s, bCase) )
+ if (GetString(i).IsSameAs(s, bCase))
return i;
}
//passed to SendMessage, so we have to do it ourselves in that case
if ( s.empty() )
{
- int count = GetCount();
- for ( int i = 0; i < count; i++ )
+ unsigned int count = GetCount();
+ for ( unsigned int i = 0; i < count; i++ )
{
- if ( GetString(i).empty() )
+ if (GetString(i).empty())
return i;
}
#endif // Watcom/!Watcom
}
-void wxChoice::SetString(int n, const wxString& s)
+void wxChoice::SetString(unsigned int n, const wxString& s)
{
- wxCHECK_RET( n >= 0 && n < GetCount(),
- wxT("invalid item index in wxChoice::SetString") );
+ wxCHECK_RET( IsValid(n), wxT("invalid item index in wxChoice::SetString") );
// we have to delete and add back the string as there is no way to change a
// string in place
InvalidateBestSize();
}
-wxString wxChoice::GetString(int n) const
+wxString wxChoice::GetString(unsigned int n) const
{
int len = (int)::SendMessage(GetHwnd(), CB_GETLBTEXTLEN, n, 0);
// client data
// ----------------------------------------------------------------------------
-void wxChoice::DoSetItemClientData( int n, void* clientData )
+void wxChoice::DoSetItemClientData(unsigned int n, void* clientData)
{
if ( ::SendMessage(GetHwnd(), CB_SETITEMDATA,
n, (LPARAM)clientData) == CB_ERR )
}
}
-void* wxChoice::DoGetItemClientData( int n ) const
+void* wxChoice::DoGetItemClientData(unsigned int n) const
{
LPARAM rc = SendMessage(GetHwnd(), CB_GETITEMDATA, n, 0);
if ( rc == CB_ERR )
return (void *)rc;
}
-void wxChoice::DoSetItemClientObject( int n, wxClientData* clientData )
+void wxChoice::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
{
DoSetItemClientData(n, clientData);
}
-wxClientData* wxChoice::DoGetItemClientObject( int n ) const
+wxClientData* wxChoice::DoGetItemClientObject(unsigned int n) const
{
return (wxClientData *)DoGetItemClientData(n);
}
int width, int height,
int sizeFlags)
{
- 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
wxControl::DoSetSize(x, y, width, height, sizeFlags);
- // I'm commenting this out since the code appears to make choices
- // and comboxes too high when they have associated sizers. I'm sure this
- // is not the end of the story, which is why I'm leaving it #if'ed out for
- // now. JACS.
+ // This solution works on XP, but causes choice/combobox lists to be
+ // too short on W2K and earlier.
#if 0
- // 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 != wxDefaultCoord )
+ int widthCurrent, heightCurrent;
+ DoGetSize(&widthCurrent, &heightCurrent);
+
+ // 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 && height != heightCurrent )
{
- const int delta = heightOrig - GetSize().y;
- if ( delta )
+ // don't make the drop down list too tall, arbitrarily limit it to 40
+ // items max and also don't leave it empty
+ unsigned int nItems = GetCount();
+ if ( !nItems )
+ nItems = 9;
+ else if ( nItems > 24 )
+ nItems = 24;
+
+ // add space for the drop down list
+ const int hItem = SendMessage(GetHwnd(), CB_GETITEMHEIGHT, 0, 0);
+ height += hItem*(nItems + 1);
+ }
+ else // keep the same height as now
+ {
+ // normally wxWindow::DoSetSize() checks if we set the same size as the
+ // window already has and does nothing in this case, but for us the
+ // check fails as the size we pass to it includes the dropdown while
+ // the size returned by our GetSize() does not, so test if the size
+ // didn't really change ourselves here
+ if ( width == wxDefaultCoord || width == widthCurrent )
{
- int h = ::SendMessage(GetHwnd(), CB_GETITEMHEIGHT, (WPARAM)-1, 0);
- SendMessage(GetHwnd(), CB_SETITEMHEIGHT, (WPARAM)-1, h + delta);
+ // size doesn't change, what about position?
+ int xCurrent, yCurrent;
+ DoGetPosition(&xCurrent, &yCurrent);
+ const bool defMeansUnchanged = !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE);
+ if ( ((x == wxDefaultCoord && defMeansUnchanged) || x == xCurrent)
+ &&
+ ((y == wxDefaultCoord && defMeansUnchanged) || y == yCurrent) )
+ {
+ // nothing changes, nothing to do
+ return;
+ }
+ }
+
+ // We cannot pass wxDefaultCoord as height to wxControl. wxControl uses
+ // wxGetWindowRect() to determine the current height of the combobox,
+ // and then again sets the combobox's height to that value. Unfortunately,
+ // wxGetWindowRect doesn't include the dropdown list's height (at least
+ // on Win2K), so this would result in a combobox with dropdown height of
+ // 1 pixel. We have to determine the default height ourselves and call
+ // wxControl with that value instead.
+ //
+ // Also notice that sometimes CB_GETDROPPEDCONTROLRECT seems to return
+ // wildly incorrect values (~32000) which looks like a bug in it, just
+ // ignore them in this case
+ RECT r;
+ if ( ::SendMessage(GetHwnd(), CB_GETDROPPEDCONTROLRECT, 0, (LPARAM) &r)
+ && r.bottom < 30000 )
+ {
+ height = heightCurrent + r.bottom - r.top;
}
}
-#else
- wxUnusedVar(heightOrig);
+
+ wxControl::DoSetSize(x, y, width, height, sizeFlags);
#endif
}
{
// find the widest string
int wChoice = 0;
- const size_t nItems = GetCount();
- for ( size_t i = 0; i < nItems; i++ )
+ const unsigned int nItems = GetCount();
+ for ( unsigned int i = 0; i < nItems; i++ )
{
int wLine;
GetTextExtent(GetString(i), &wLine, NULL);
if ( n > -1 )
{
event.SetString(GetStringSelection());
- if ( HasClientObjectData() )
- event.SetClientObject( GetClientObject(n) );
- else if ( HasClientUntypedData() )
- event.SetClientData( GetClientData(n) );
+ InitCommandEventWithItems(event, n);
}
ProcessCommand(event);