// initialize the controls contents
- for ( int i = 0; i < n; i++ )
- {
- Append(choices[i]);
- }
+ Append(n, choices);
// and now we may finally size the control properly (if needed)
SetInitialSize(size);
else if ( HasClientObjectData() )
oldObjData = GetClientObject(n);
+ // and also the selection if we're going to delete the item that was
+ // selected
+ const bool wasSelected = static_cast<int>(n) == GetSelection();
+
::SendMessage(GetHwnd(), CB_DELETESTRING, n, 0);
::SendMessage(GetHwnd(), CB_INSERTSTRING, n, (LPARAM)s.wx_str() );
else if ( oldObjData )
SetClientObject(n, oldObjData);
+ // and the selection
+ if ( wasSelected )
+ SetSelection(n);
+
+ // the width could have changed so the best size needs to be recomputed
InvalidateBestSize();
}
void* wxChoice::DoGetItemClientData(unsigned int n) const
{
LPARAM rc = SendMessage(GetHwnd(), CB_GETITEMDATA, n, 0);
- if ( rc == CB_ERR )
+ if ( rc == CB_ERR && GetLastError() != ERROR_SUCCESS )
{
wxLogLastError(wxT("CB_GETITEMDATA"));
const int hItem = SendMessage(GetHwnd(), CB_GETITEMHEIGHT, 0, 0);
int heightWithItems = 0;
if (!HasFlag(wxCB_SIMPLE))
- heightWithItems = height + hItem*nItems;
+ // The extra item (" + 1") is required to prevent a vertical
+ // scrollbar from appearing with comctl32.dll versions earlier
+ // than 6.0 (such as found in Win2k).
+ heightWithItems = height + hItem*(nItems + 1);
else
heightWithItems = SetHeightSimpleComboBox(nItems);
// 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
+ // useless 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 )
return EDIT_HEIGHT_FROM_CHAR_HEIGHT( cy ) * wxMin( wxMax( nItems, 3 ), 6 ) + hItem - 1;
}
+// ----------------------------------------------------------------------------
+// Popup operations
+// ----------------------------------------------------------------------------
+
+void wxChoice::MSWDoPopupOrDismiss(bool show)
+{
+ wxASSERT_MSG( !HasFlag(wxCB_SIMPLE),
+ wxT("can't popup/dismiss the list for simple combo box") );
+
+ // we *must* set focus to the combobox before showing or hiding the drop
+ // down as without this we get WM_LBUTTONDOWN messages with invalid HWND
+ // when hiding it (whether programmatically or manually) resulting in a
+ // crash when we pass them to IsDialogMessage()
+ //
+ // this can be seen in the combo page of the widgets sample under Windows 7
+ SetFocus();
+
+ ::SendMessage(GetHwnd(), CB_SHOWDROPDOWN, show, 0);
+}
+
+bool wxChoice::Show(bool show)
+{
+ if ( !wxChoiceBase::Show(show) )
+ return false;
+
+ // When hiding the combobox, we also need to hide its popup part as it
+ // doesn't happen automatically.
+ if ( !show && ::SendMessage(GetHwnd(), CB_GETDROPPEDSTATE, 0, 0) )
+ MSWDoPopupOrDismiss(false);
+
+ return true;
+}
+
// ----------------------------------------------------------------------------
// MSW message handlers
// ----------------------------------------------------------------------------
WXHBRUSH wxChoice::MSWControlColor(WXHDC hDC, WXHWND hWnd)
{
- if ( !IsEnabled() )
+ if ( !IsThisEnabled() )
return MSWControlColorDisabled(hDC);
return wxChoiceBase::MSWControlColor(hDC, hWnd);