]> git.saurik.com Git - wxWidgets.git/blame - src/msw/bmpcbox.cpp
wxTLW: don't assert when setting null icons initially (#10138)
[wxWidgets.git] / src / msw / bmpcbox.cpp
CommitLineData
f696015c
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/bmpcboxg.cpp
3// Purpose: wxBitmapComboBox
4// Author: Jaakko Salli
5// Created: 2008-04-06
6// RCS-ID: $Id:$
7// Copyright: (c) 2008 Jaakko Salli
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19#include "wx/wxprec.h"
20
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
25#if wxUSE_BITMAPCOMBOBOX
26
27#include "wx/bmpcbox.h"
28
29#ifndef WX_PRECOMP
30 #include "wx/log.h"
31#endif
32
33#include "wx/settings.h"
34
35#include "wx/msw/dcclient.h"
36#include "wx/msw/private.h"
37
38// For wxODCB_XXX flags
39#include "wx/odcombo.h"
40
41
42#define IMAGE_SPACING_CTRL_VERTICAL 7 // Spacing used in control size calculation
43
44
45// ============================================================================
46// implementation
47// ============================================================================
48
49
50BEGIN_EVENT_TABLE(wxBitmapComboBox, wxComboBox)
51 EVT_SIZE(wxBitmapComboBox::OnSize)
52END_EVENT_TABLE()
53
54
55IMPLEMENT_DYNAMIC_CLASS(wxBitmapComboBox, wxComboBox)
56
57
58// ----------------------------------------------------------------------------
59// wxBitmapComboBox creation
60// ----------------------------------------------------------------------------
61
62void wxBitmapComboBox::Init()
63{
64 m_inResize = false;
65}
66
67wxBitmapComboBox::wxBitmapComboBox(wxWindow *parent,
68 wxWindowID id,
69 const wxString& value,
70 const wxPoint& pos,
71 const wxSize& size,
72 const wxArrayString& choices,
73 long style,
74 const wxValidator& validator,
75 const wxString& name)
76 : wxComboBox(),
77 wxBitmapComboBoxBase()
78{
79 Init();
80
81 Create(parent,id,value,pos,size,choices,style,validator,name);
82}
83
84bool wxBitmapComboBox::Create(wxWindow *parent,
85 wxWindowID id,
86 const wxString& value,
87 const wxPoint& pos,
88 const wxSize& size,
89 const wxArrayString& choices,
90 long style,
91 const wxValidator& validator,
92 const wxString& name)
93{
94 wxCArrayString chs(choices);
95 return Create(parent, id, value, pos, size, chs.GetCount(),
96 chs.GetStrings(), style, validator, name);
97}
98
99bool wxBitmapComboBox::Create(wxWindow *parent,
100 wxWindowID id,
101 const wxString& value,
102 const wxPoint& pos,
103 const wxSize& size,
104 int n,
105 const wxString choices[],
106 long style,
107 const wxValidator& validator,
108 const wxString& name)
109{
110 if ( !wxComboBox::Create(parent, id, value, pos, size,
111 n, choices, style, validator, name) )
112 return false;
113
114 UpdateInternals();
115
116 return true;
117}
118
119WXDWORD wxBitmapComboBox::MSWGetStyle(long style, WXDWORD *exstyle) const
120{
121 return wxComboBox::MSWGetStyle(style, exstyle) | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS;
122}
123
124void wxBitmapComboBox::RecreateControl()
125{
126 //
127 // Recreate control so that WM_MEASUREITEM gets called again.
128 // Can't use CBS_OWNERDRAWVARIABLE because it has odd
129 // mouse-wheel behaviour.
130 //
131 wxString value = GetValue();
132 wxPoint pos = GetPosition();
133 wxSize size = GetSize();
134 wxArrayString strings = GetStrings();
135
136 wxComboBox::DoClear();
137
138 HWND hwnd = GetHwnd();
139 DissociateHandle();
140 ::DestroyWindow(hwnd);
141
142 if ( !MSWCreateControl(wxT("COMBOBOX"), value, pos, size) )
143 return;
144
145 // initialize the controls contents
146 for ( unsigned int i = 0; i < strings.size(); i++ )
147 {
148 wxComboBox::Append(strings[i]);
149 }
150
151 // and make sure it has the same attributes as before
152 if ( m_hasFont )
153 {
154 // calling SetFont(m_font) would do nothing as the code would
155 // notice that the font didn't change, so force it to believe
156 // that it did
157 wxFont font = m_font;
158 m_font = wxNullFont;
159 SetFont(font);
160 }
161
162 if ( m_hasFgCol )
163 {
164 wxColour colFg = m_foregroundColour;
165 m_foregroundColour = wxNullColour;
166 SetForegroundColour(colFg);
167 }
168
169 if ( m_hasBgCol )
170 {
171 wxColour colBg = m_backgroundColour;
172 m_backgroundColour = wxNullColour;
173 SetBackgroundColour(colBg);
174 }
175 else
176 {
177 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
178 }
179}
180
181wxBitmapComboBox::~wxBitmapComboBox()
182{
183 Clear();
184}
185
186// ----------------------------------------------------------------------------
187// Item manipulation
188// ----------------------------------------------------------------------------
189
190void wxBitmapComboBox::SetItemBitmap(unsigned int n, const wxBitmap& bitmap)
191{
192 OnAddBitmap(bitmap);
193 DoSetItemBitmap(n, bitmap);
194
195 if ( (int)n == GetSelection() )
196 Refresh();
197}
198
199int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap)
200{
201 OnAddBitmap(bitmap);
202 const int n = wxComboBox::Append(item);
203 if ( n != wxNOT_FOUND )
204 DoSetItemBitmap(n, bitmap);
205 return n;
206}
207
208int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
209 void *clientData)
210{
211 OnAddBitmap(bitmap);
212 const int n = wxComboBox::Append(item, clientData);
213 if ( n != wxNOT_FOUND )
214 DoSetItemBitmap(n, bitmap);
215 return n;
216}
217
218int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
219 wxClientData *clientData)
220{
221 OnAddBitmap(bitmap);
222 const int n = wxComboBox::Append(item, clientData);
223 if ( n != wxNOT_FOUND )
224 DoSetItemBitmap(n, bitmap);
225 return n;
226}
227
228int wxBitmapComboBox::Insert(const wxString& item,
229 const wxBitmap& bitmap,
230 unsigned int pos)
231{
232 OnAddBitmap(bitmap);
233 const int n = wxComboBox::Insert(item, pos);
234 if ( n != wxNOT_FOUND )
235 DoSetItemBitmap(n, bitmap);
236 return n;
237}
238
239int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
240 unsigned int pos, wxClientData *clientData)
241{
242 OnAddBitmap(bitmap);
243 const int n = wxComboBox::Insert(item, pos, clientData);
244 if ( n != wxNOT_FOUND )
245 DoSetItemBitmap(n, bitmap);
246 return n;
247}
248
249int wxBitmapComboBox::DoInsertItems(const wxArrayStringsAdapter & items,
250 unsigned int pos,
251 void **clientData, wxClientDataType type)
252{
253 const unsigned int numItems = items.GetCount();
254 const unsigned int countNew = GetCount() + numItems;
255
256 m_bitmaps.Alloc(countNew);
257
258 for ( unsigned int i = 0; i < numItems; i++ )
259 {
260 m_bitmaps.Insert(new wxBitmap(wxNullBitmap), pos + i);
261 }
262
263 const int index = wxComboBox::DoInsertItems(items, pos,
264 clientData, type);
265
266 if ( index == wxNOT_FOUND )
267 {
268 for ( int i = numItems-1; i >= 0; i-- )
269 BCBDoDeleteOneItem(pos + i);
270 }
271
272 return index;
273}
274
275bool wxBitmapComboBox::OnAddBitmap(const wxBitmap& bitmap)
276{
277 if ( wxBitmapComboBoxBase::OnAddBitmap(bitmap) )
278 {
279 // Need to recreate control for a new measureitem call?
280 int prevItemHeight = ::SendMessage(GetHwnd(), CB_GETITEMHEIGHT, 0, 0);
281
282 if ( prevItemHeight != MeasureItem(0) )
283 RecreateControl();
284
285 return true;
286 }
287
288 return false;
289}
290
291void wxBitmapComboBox::DoClear()
292{
293 wxComboBox::DoClear();
294 wxBitmapComboBoxBase::BCBDoClear();
295}
296
297void wxBitmapComboBox::DoDeleteOneItem(unsigned int n)
298{
299 wxComboBox::DoDeleteOneItem(n);
300 wxBitmapComboBoxBase::BCBDoDeleteOneItem(n);
301}
302
303// ----------------------------------------------------------------------------
304// wxBitmapComboBox event handlers and such
305// ----------------------------------------------------------------------------
306
307void wxBitmapComboBox::OnSize(wxSizeEvent& event)
308{
309 // Prevent infinite looping
310 if ( !m_inResize )
311 {
312 m_inResize = true;
313 DetermineIndent();
314 m_inResize = false;
315 }
316
317 event.Skip();
318}
319
320// ----------------------------------------------------------------------------
321// wxBitmapComboBox miscellaneous
322// ----------------------------------------------------------------------------
323
324bool wxBitmapComboBox::SetFont(const wxFont& font)
325{
326 bool res = wxComboBox::SetFont(font);
327 UpdateInternals();
328 return res;
329}
330
331// ----------------------------------------------------------------------------
332// wxBitmapComboBox item drawing and measuring
333// ----------------------------------------------------------------------------
334
335bool wxBitmapComboBox::MSWOnDraw(WXDRAWITEMSTRUCT *item)
336{
337 LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT) item;
338 int pos = lpDrawItem->itemID;
339
340 // Draw default for item -1, which means 'focus rect only'
341 if ( pos == -1 )
342 return FALSE;
343
344 int flags = 0;
345 if ( lpDrawItem->itemState & ODS_COMBOBOXEDIT )
346 flags |= wxODCB_PAINTING_CONTROL;
347 if ( lpDrawItem->itemState & ODS_SELECTED )
348 flags |= wxODCB_PAINTING_SELECTED;
349
350 wxString text;
351
352 if ( flags & wxODCB_PAINTING_CONTROL )
353 {
354 text = GetValue();
355 if ( !HasFlag(wxCB_READONLY) )
356 text.clear();
357 }
358 else
359 {
360 text = GetString(pos);
361 }
362
363 wxPaintDCEx dc(this, lpDrawItem->hDC);
364 wxRect rect = wxRectFromRECT(lpDrawItem->rcItem);
365 wxBitmapComboBoxBase::DrawBackground(dc, rect, pos, flags);
366 wxBitmapComboBoxBase::DrawItem(dc, rect, pos, text, flags);
367
368 // If the item has the focus, draw focus rectangle.
369 // Commented out since regular combo box doesn't
370 // seem to do it either.
371 //if ( lpDrawItem->itemState & ODS_FOCUS )
372 // DrawFocusRect(lpDrawItem->hDC, &lpDrawItem->rcItem);
373
374 return TRUE;
375}
376
377bool wxBitmapComboBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
378{
379 LPMEASUREITEMSTRUCT lpMeasureItem = (LPMEASUREITEMSTRUCT) item;
380 int pos = lpMeasureItem->itemID;
381
382 lpMeasureItem->itemHeight = wxBitmapComboBoxBase::MeasureItem(pos);
383
384 return TRUE;
385}
386
387#endif // wxUSE_BITMAPCOMBOBOX