///////////////////////////////////////////////////////////////////////////// // Name: src/msw/bmpcboxg.cpp // Purpose: wxBitmapComboBox // Author: Jaakko Salli // Created: 2008-04-06 // RCS-ID: $Id$ // Copyright: (c) 2008 Jaakko Salli // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ // declarations // ============================================================================ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #if wxUSE_BITMAPCOMBOBOX #include "wx/bmpcbox.h" #ifndef WX_PRECOMP #include "wx/log.h" #endif #include "wx/settings.h" #include "wx/msw/dcclient.h" #include "wx/msw/private.h" // For wxODCB_XXX flags #include "wx/odcombo.h" #define IMAGE_SPACING_CTRL_VERTICAL 7 // Spacing used in control size calculation // ============================================================================ // implementation // ============================================================================ BEGIN_EVENT_TABLE(wxBitmapComboBox, wxComboBox) EVT_SIZE(wxBitmapComboBox::OnSize) END_EVENT_TABLE() IMPLEMENT_DYNAMIC_CLASS(wxBitmapComboBox, wxComboBox) // ---------------------------------------------------------------------------- // wxBitmapComboBox creation // ---------------------------------------------------------------------------- void wxBitmapComboBox::Init() { m_inResize = false; } wxBitmapComboBox::wxBitmapComboBox(wxWindow *parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, const wxArrayString& choices, long style, const wxValidator& validator, const wxString& name) : wxComboBox(), wxBitmapComboBoxBase() { Init(); Create(parent,id,value,pos,size,choices,style,validator,name); } bool wxBitmapComboBox::Create(wxWindow *parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, const wxArrayString& choices, long style, const wxValidator& validator, const wxString& name) { wxCArrayString chs(choices); return Create(parent, id, value, pos, size, chs.GetCount(), chs.GetStrings(), style, validator, name); } bool wxBitmapComboBox::Create(wxWindow *parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, int n, const wxString choices[], long style, const wxValidator& validator, const wxString& name) { if ( !wxComboBox::Create(parent, id, value, pos, size, n, choices, style, validator, name) ) return false; UpdateInternals(); return true; } WXDWORD wxBitmapComboBox::MSWGetStyle(long style, WXDWORD *exstyle) const { return wxComboBox::MSWGetStyle(style, exstyle) | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS; } void wxBitmapComboBox::RecreateControl() { // // Recreate control so that WM_MEASUREITEM gets called again. // Can't use CBS_OWNERDRAWVARIABLE because it has odd // mouse-wheel behaviour. // wxString value = GetValue(); wxPoint pos = GetPosition(); wxSize size = GetSize(); wxArrayString strings = GetStrings(); wxComboBox::DoClear(); HWND hwnd = GetHwnd(); DissociateHandle(); ::DestroyWindow(hwnd); if ( !MSWCreateControl(wxT("COMBOBOX"), value, pos, size) ) return; // initialize the controls contents for ( unsigned int i = 0; i < strings.size(); i++ ) { wxComboBox::Append(strings[i]); } // and make sure it has the same attributes as before if ( m_hasFont ) { // calling SetFont(m_font) would do nothing as the code would // notice that the font didn't change, so force it to believe // that it did wxFont font = m_font; m_font = wxNullFont; SetFont(font); } if ( m_hasFgCol ) { wxColour colFg = m_foregroundColour; m_foregroundColour = wxNullColour; SetForegroundColour(colFg); } if ( m_hasBgCol ) { wxColour colBg = m_backgroundColour; m_backgroundColour = wxNullColour; SetBackgroundColour(colBg); } else { SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); } } wxBitmapComboBox::~wxBitmapComboBox() { Clear(); } // ---------------------------------------------------------------------------- // Item manipulation // ---------------------------------------------------------------------------- void wxBitmapComboBox::SetItemBitmap(unsigned int n, const wxBitmap& bitmap) { OnAddBitmap(bitmap); DoSetItemBitmap(n, bitmap); if ( (int)n == GetSelection() ) Refresh(); } int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap) { OnAddBitmap(bitmap); const int n = wxComboBox::Append(item); if ( n != wxNOT_FOUND ) DoSetItemBitmap(n, bitmap); return n; } int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap, void *clientData) { OnAddBitmap(bitmap); const int n = wxComboBox::Append(item, clientData); if ( n != wxNOT_FOUND ) DoSetItemBitmap(n, bitmap); return n; } int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap, wxClientData *clientData) { OnAddBitmap(bitmap); const int n = wxComboBox::Append(item, clientData); if ( n != wxNOT_FOUND ) DoSetItemBitmap(n, bitmap); return n; } int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap, unsigned int pos) { OnAddBitmap(bitmap); const int n = wxComboBox::Insert(item, pos); if ( n != wxNOT_FOUND ) DoSetItemBitmap(n, bitmap); return n; } int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap, unsigned int pos, wxClientData *clientData) { OnAddBitmap(bitmap); const int n = wxComboBox::Insert(item, pos, clientData); if ( n != wxNOT_FOUND ) DoSetItemBitmap(n, bitmap); return n; } int wxBitmapComboBox::DoInsertItems(const wxArrayStringsAdapter & items, unsigned int pos, void **clientData, wxClientDataType type) { const unsigned int numItems = items.GetCount(); const unsigned int countNew = GetCount() + numItems; m_bitmaps.Alloc(countNew); for ( unsigned int i = 0; i < numItems; i++ ) { m_bitmaps.Insert(new wxBitmap(wxNullBitmap), pos + i); } const int index = wxComboBox::DoInsertItems(items, pos, clientData, type); if ( index == wxNOT_FOUND ) { for ( int i = numItems-1; i >= 0; i-- ) BCBDoDeleteOneItem(pos + i); } return index; } bool wxBitmapComboBox::OnAddBitmap(const wxBitmap& bitmap) { if ( wxBitmapComboBoxBase::OnAddBitmap(bitmap) ) { // Need to recreate control for a new measureitem call? int prevItemHeight = ::SendMessage(GetHwnd(), CB_GETITEMHEIGHT, 0, 0); if ( prevItemHeight != MeasureItem(0) ) RecreateControl(); return true; } return false; } void wxBitmapComboBox::DoClear() { wxComboBox::DoClear(); wxBitmapComboBoxBase::BCBDoClear(); } void wxBitmapComboBox::DoDeleteOneItem(unsigned int n) { wxComboBox::DoDeleteOneItem(n); wxBitmapComboBoxBase::BCBDoDeleteOneItem(n); } // ---------------------------------------------------------------------------- // wxBitmapComboBox event handlers and such // ---------------------------------------------------------------------------- void wxBitmapComboBox::OnSize(wxSizeEvent& event) { // Prevent infinite looping if ( !m_inResize ) { m_inResize = true; DetermineIndent(); m_inResize = false; } event.Skip(); } // ---------------------------------------------------------------------------- // wxBitmapComboBox miscellaneous // ---------------------------------------------------------------------------- bool wxBitmapComboBox::SetFont(const wxFont& font) { bool res = wxComboBox::SetFont(font); UpdateInternals(); return res; } // ---------------------------------------------------------------------------- // wxBitmapComboBox item drawing and measuring // ---------------------------------------------------------------------------- bool wxBitmapComboBox::MSWOnDraw(WXDRAWITEMSTRUCT *item) { LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT) item; int pos = lpDrawItem->itemID; // Draw default for item -1, which means 'focus rect only' if ( pos == -1 ) return FALSE; int flags = 0; if ( lpDrawItem->itemState & ODS_COMBOBOXEDIT ) flags |= wxODCB_PAINTING_CONTROL; if ( lpDrawItem->itemState & ODS_SELECTED ) flags |= wxODCB_PAINTING_SELECTED; wxString text; if ( flags & wxODCB_PAINTING_CONTROL ) { text = GetValue(); if ( !HasFlag(wxCB_READONLY) ) text.clear(); } else { text = GetString(pos); } wxPaintDCEx dc(this, lpDrawItem->hDC); wxRect rect = wxRectFromRECT(lpDrawItem->rcItem); wxBitmapComboBoxBase::DrawBackground(dc, rect, pos, flags); wxBitmapComboBoxBase::DrawItem(dc, rect, pos, text, flags); // If the item has the focus, draw focus rectangle. // Commented out since regular combo box doesn't // seem to do it either. //if ( lpDrawItem->itemState & ODS_FOCUS ) // DrawFocusRect(lpDrawItem->hDC, &lpDrawItem->rcItem); return TRUE; } bool wxBitmapComboBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item) { LPMEASUREITEMSTRUCT lpMeasureItem = (LPMEASUREITEMSTRUCT) item; int pos = lpMeasureItem->itemID; lpMeasureItem->itemHeight = wxBitmapComboBoxBase::MeasureItem(pos); return TRUE; } #endif // wxUSE_BITMAPCOMBOBOX