]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/listbox.cpp
Acutally use the m_maxChars parameter value instead of ignoring it
[wxWidgets.git] / src / msw / listbox.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/listbox.cpp
3// Purpose: wxListBox
4// Author: Julian Smart
5// Modified by: Vadim Zeitlin (owner drawn stuff)
6// Created:
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13 #pragma implementation "listbox.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
23#if wxUSE_LISTBOX
24
25#ifndef WX_PRECOMP
26#include "wx/listbox.h"
27#include "wx/settings.h"
28#include "wx/brush.h"
29#include "wx/font.h"
30#include "wx/dc.h"
31#include "wx/utils.h"
32#endif
33
34#include "wx/window.h"
35#include "wx/msw/private.h"
36
37#include <windowsx.h>
38
39#include "wx/dynarray.h"
40#include "wx/log.h"
41
42#if wxUSE_OWNER_DRAWN
43 #include "wx/ownerdrw.h"
44#endif
45
46#ifndef __TWIN32__
47 #ifdef __GNUWIN32_OLD__
48 #include "wx/msw/gnuwin32/extra.h"
49 #endif
50#endif
51
52IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
53
54// ============================================================================
55// list box item declaration and implementation
56// ============================================================================
57
58#if wxUSE_OWNER_DRAWN
59
60class wxListBoxItem : public wxOwnerDrawn
61{
62public:
63 wxListBoxItem(const wxString& str = wxEmptyString);
64};
65
66wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE)
67{
68 // no bitmaps/checkmarks
69 SetMarginWidth(0);
70}
71
72wxOwnerDrawn *wxListBox::CreateLboxItem(size_t WXUNUSED(n))
73{
74 return new wxListBoxItem();
75}
76
77#endif //USE_OWNER_DRAWN
78
79// ============================================================================
80// list box control implementation
81// ============================================================================
82
83// ----------------------------------------------------------------------------
84// creation
85// ----------------------------------------------------------------------------
86
87// Listbox item
88wxListBox::wxListBox()
89{
90 m_noItems = 0;
91 m_selected = 0;
92}
93
94bool wxListBox::Create(wxWindow *parent,
95 wxWindowID id,
96 const wxPoint& pos,
97 const wxSize& size,
98 int n, const wxString choices[],
99 long style,
100 const wxValidator& validator,
101 const wxString& name)
102{
103 m_noItems = 0;
104 m_hWnd = 0;
105 m_selected = 0;
106
107 SetName(name);
108#if wxUSE_VALIDATORS
109 SetValidator(validator);
110#endif // wxUSE_VALIDATORS
111
112 if (parent)
113 parent->AddChild(this);
114
115 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
116 SetForegroundColour(parent->GetForegroundColour());
117
118 m_windowId = ( id == -1 ) ? (int)NewControlId() : id;
119
120 int x = pos.x;
121 int y = pos.y;
122 int width = size.x;
123 int height = size.y;
124 m_windowStyle = style;
125
126 DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_VSCROLL | WS_TABSTOP |
127 LBS_NOTIFY | LBS_HASSTRINGS ;
128
129 wxASSERT_MSG( !(style & wxLB_MULTIPLE) || !(style & wxLB_EXTENDED),
130 _T("only one of listbox selection modes can be specified") );
131
132 if ( (m_windowStyle & wxBORDER_MASK) == wxBORDER_DEFAULT )
133 m_windowStyle |= wxBORDER_SUNKEN;
134
135 if ( m_windowStyle & wxCLIP_SIBLINGS )
136 wstyle |= WS_CLIPSIBLINGS;
137
138 if (m_windowStyle & wxLB_MULTIPLE)
139 wstyle |= LBS_MULTIPLESEL;
140 else if (m_windowStyle & wxLB_EXTENDED)
141 wstyle |= LBS_EXTENDEDSEL;
142
143 if (m_windowStyle & wxLB_ALWAYS_SB)
144 wstyle |= LBS_DISABLENOSCROLL;
145 if (m_windowStyle & wxLB_HSCROLL)
146 wstyle |= WS_HSCROLL;
147 if (m_windowStyle & wxLB_SORT)
148 wstyle |= LBS_SORT;
149
150#if wxUSE_OWNER_DRAWN
151 if ( m_windowStyle & wxLB_OWNERDRAW ) {
152 // we don't support LBS_OWNERDRAWVARIABLE yet
153 wstyle |= LBS_OWNERDRAWFIXED;
154 }
155#endif
156
157 // Without this style, you get unexpected heights, so e.g. constraint layout
158 // doesn't work properly
159 wstyle |= LBS_NOINTEGRALHEIGHT;
160
161 WXDWORD exStyle = 0;
162 (void) MSWGetStyle(m_windowStyle, & exStyle) ;
163
164 m_hWnd = (WXHWND)::CreateWindowEx(exStyle, wxT("LISTBOX"), NULL,
165 wstyle ,
166 0, 0, 0, 0,
167 (HWND)parent->GetHWND(), (HMENU)m_windowId,
168 wxGetInstance(), NULL);
169
170 wxCHECK_MSG( m_hWnd, FALSE, wxT("Failed to create listbox") );
171
172 // Subclass again to catch messages
173 SubclassWin(m_hWnd);
174
175 size_t ui;
176 for (ui = 0; ui < (size_t)n; ui++) {
177 Append(choices[ui]);
178 }
179
180 if ( (m_windowStyle & wxLB_MULTIPLE) == 0 )
181 SendMessage(GetHwnd(), LB_SETCURSEL, 0, 0);
182
183 SetFont(parent->GetFont());
184
185 SetSize(x, y, width, height);
186
187 return TRUE;
188}
189
190wxListBox::~wxListBox()
191{
192 Free();
193}
194
195void wxListBox::SetupColours()
196{
197 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
198 SetForegroundColour(GetParent()->GetForegroundColour());
199}
200
201// ----------------------------------------------------------------------------
202// implementation of wxListBoxBase methods
203// ----------------------------------------------------------------------------
204
205void wxListBox::DoSetFirstItem(int N)
206{
207 wxCHECK_RET( N >= 0 && N < m_noItems,
208 wxT("invalid index in wxListBox::SetFirstItem") );
209
210 SendMessage(GetHwnd(), LB_SETTOPINDEX, (WPARAM)N, (LPARAM)0);
211}
212
213void wxListBox::Delete(int N)
214{
215 wxCHECK_RET( N >= 0 && N < m_noItems,
216 wxT("invalid index in wxListBox::Delete") );
217
218 // for owner drawn objects, the data is used for storing wxOwnerDrawn
219 // pointers and we shouldn't touch it
220#if !wxUSE_OWNER_DRAWN
221 if ( !(m_windowStyle & wxLB_OWNERDRAW) )
222#endif // !wxUSE_OWNER_DRAWN
223 if ( HasClientObjectData() )
224 {
225 delete GetClientObject(N);
226 }
227
228 SendMessage(GetHwnd(), LB_DELETESTRING, N, 0);
229 m_noItems--;
230
231 SetHorizontalExtent(wxEmptyString);
232}
233
234int wxListBox::DoAppend(const wxString& item)
235{
236 int index = ListBox_AddString(GetHwnd(), item);
237 m_noItems++;
238
239#if wxUSE_OWNER_DRAWN
240 if ( m_windowStyle & wxLB_OWNERDRAW ) {
241 wxOwnerDrawn *pNewItem = CreateLboxItem(index); // dummy argument
242 pNewItem->SetName(item);
243 m_aItems.Insert(pNewItem, index);
244 ListBox_SetItemData(GetHwnd(), index, pNewItem);
245 pNewItem->SetFont(GetFont());
246 }
247#endif // wxUSE_OWNER_DRAWN
248
249 SetHorizontalExtent(item);
250
251 return index;
252}
253
254void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
255{
256 // avoid flicker - but don't need to do this for a hidden listbox
257 bool hideAndShow = IsShown();
258 if ( hideAndShow )
259 {
260 ShowWindow(GetHwnd(), SW_HIDE);
261 }
262
263 ListBox_ResetContent(GetHwnd());
264
265 m_noItems = choices.GetCount();
266 int i;
267 for (i = 0; i < m_noItems; i++)
268 {
269 ListBox_AddString(GetHwnd(), choices[i]);
270 if ( clientData )
271 {
272 SetClientData(i, clientData[i]);
273 }
274 }
275
276#if wxUSE_OWNER_DRAWN
277 if ( m_windowStyle & wxLB_OWNERDRAW ) {
278 // first delete old items
279 WX_CLEAR_ARRAY(m_aItems);
280
281 // then create new ones
282 for ( size_t ui = 0; ui < (size_t)m_noItems; ui++ ) {
283 wxOwnerDrawn *pNewItem = CreateLboxItem(ui);
284 pNewItem->SetName(choices[ui]);
285 m_aItems.Add(pNewItem);
286 ListBox_SetItemData(GetHwnd(), ui, pNewItem);
287 }
288 }
289#endif // wxUSE_OWNER_DRAWN
290
291 SetHorizontalExtent();
292
293 if ( hideAndShow )
294 {
295 // show the listbox back if we hid it
296 ShowWindow(GetHwnd(), SW_SHOW);
297 }
298}
299
300int wxListBox::FindString(const wxString& s) const
301{
302 int pos = ListBox_FindStringExact(GetHwnd(), (WPARAM)-1, s);
303 if (pos == LB_ERR)
304 return wxNOT_FOUND;
305 else
306 return pos;
307}
308
309void wxListBox::Clear()
310{
311 Free();
312
313 ListBox_ResetContent(GetHwnd());
314
315 m_noItems = 0;
316 SetHorizontalExtent();
317}
318
319void wxListBox::Free()
320{
321#if wxUSE_OWNER_DRAWN
322 if ( m_windowStyle & wxLB_OWNERDRAW )
323 {
324 WX_CLEAR_ARRAY(m_aItems);
325 }
326 else
327#endif // wxUSE_OWNER_DRAWN
328 if ( HasClientObjectData() )
329 {
330 for ( size_t n = 0; n < (size_t)m_noItems; n++ )
331 {
332 delete GetClientObject(n);
333 }
334 }
335}
336
337void wxListBox::SetSelection(int N, bool select)
338{
339 wxCHECK_RET( N >= 0 && N < m_noItems,
340 wxT("invalid index in wxListBox::SetSelection") );
341
342 if ( HasMultipleSelection() )
343 {
344 SendMessage(GetHwnd(), LB_SETSEL, select, N);
345 }
346 else
347 {
348 SendMessage(GetHwnd(), LB_SETCURSEL, select ? N : -1, 0);
349 }
350}
351
352bool wxListBox::IsSelected(int N) const
353{
354 wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE,
355 wxT("invalid index in wxListBox::Selected") );
356
357 return SendMessage(GetHwnd(), LB_GETSEL, N, 0) == 0 ? FALSE : TRUE;
358}
359
360wxClientData* wxListBox::DoGetItemClientObject(int n) const
361{
362 return (wxClientData *)DoGetItemClientData(n);
363}
364
365void *wxListBox::DoGetItemClientData(int n) const
366{
367 wxCHECK_MSG( n >= 0 && n < m_noItems, NULL,
368 wxT("invalid index in wxListBox::GetClientData") );
369
370 return (void *)SendMessage(GetHwnd(), LB_GETITEMDATA, n, 0);
371}
372
373void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
374{
375 DoSetItemClientData(n, clientData);
376}
377
378void wxListBox::DoSetItemClientData(int n, void *clientData)
379{
380 wxCHECK_RET( n >= 0 && n < m_noItems,
381 wxT("invalid index in wxListBox::SetClientData") );
382
383#if wxUSE_OWNER_DRAWN
384 if ( m_windowStyle & wxLB_OWNERDRAW )
385 {
386 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
387 // in OnMeasure/OnDraw.
388 wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes"));
389 }
390#endif // wxUSE_OWNER_DRAWN
391
392 if ( ListBox_SetItemData(GetHwnd(), n, clientData) == LB_ERR )
393 wxLogDebug(wxT("LB_SETITEMDATA failed"));
394}
395
396// Return number of selections and an array of selected integers
397int wxListBox::GetSelections(wxArrayInt& aSelections) const
398{
399 aSelections.Empty();
400
401 if ( HasMultipleSelection() )
402 {
403 int countSel = ListBox_GetSelCount(GetHwnd());
404 if ( countSel == LB_ERR )
405 {
406 wxLogDebug(_T("ListBox_GetSelCount failed"));
407 }
408 else if ( countSel != 0 )
409 {
410 int *selections = new int[countSel];
411
412 if ( ListBox_GetSelItems(GetHwnd(),
413 countSel, selections) == LB_ERR )
414 {
415 wxLogDebug(wxT("ListBox_GetSelItems failed"));
416 countSel = -1;
417 }
418 else
419 {
420 aSelections.Alloc(countSel);
421 for ( int n = 0; n < countSel; n++ )
422 aSelections.Add(selections[n]);
423 }
424
425 delete [] selections;
426 }
427
428 return countSel;
429 }
430 else // single-selection listbox
431 {
432 if (ListBox_GetCurSel(GetHwnd()) > -1)
433 aSelections.Add(ListBox_GetCurSel(GetHwnd()));
434
435 return aSelections.Count();
436 }
437}
438
439// Get single selection, for single choice list items
440int wxListBox::GetSelection() const
441{
442 wxCHECK_MSG( !HasMultipleSelection(),
443 -1,
444 wxT("GetSelection() can't be used with multiple-selection listboxes, use GetSelections() instead.") );
445
446 return ListBox_GetCurSel(GetHwnd());
447}
448
449// Find string for position
450wxString wxListBox::GetString(int N) const
451{
452 wxCHECK_MSG( N >= 0 && N < m_noItems, wxEmptyString,
453 wxT("invalid index in wxListBox::GetClientData") );
454
455 int len = ListBox_GetTextLen(GetHwnd(), N);
456
457 // +1 for terminating NUL
458 wxString result;
459 ListBox_GetText(GetHwnd(), N, result.GetWriteBuf(len + 1));
460 result.UngetWriteBuf();
461
462 return result;
463}
464
465void
466wxListBox::DoInsertItems(const wxArrayString& items, int pos)
467{
468 wxCHECK_RET( pos >= 0 && pos <= m_noItems,
469 wxT("invalid index in wxListBox::InsertItems") );
470
471 int nItems = items.GetCount();
472 for ( int i = 0; i < nItems; i++ )
473 {
474 int idx = ListBox_InsertString(GetHwnd(), i + pos, items[i]);
475
476#if wxUSE_OWNER_DRAWN
477 if ( m_windowStyle & wxLB_OWNERDRAW )
478 {
479 wxOwnerDrawn *pNewItem = CreateLboxItem(idx);
480 pNewItem->SetName(items[i]);
481 pNewItem->SetFont(GetFont());
482 m_aItems.Insert(pNewItem, idx);
483
484 ListBox_SetItemData(GetHwnd(), idx, pNewItem);
485 }
486#endif // wxUSE_OWNER_DRAWN
487 }
488
489 m_noItems += nItems;
490
491 SetHorizontalExtent();
492}
493
494void wxListBox::SetString(int N, const wxString& s)
495{
496 wxCHECK_RET( N >= 0 && N < m_noItems,
497 wxT("invalid index in wxListBox::SetString") );
498
499 // remember the state of the item
500 bool wasSelected = IsSelected(N);
501
502 void *oldData = NULL;
503 wxClientData *oldObjData = NULL;
504 if ( m_clientDataItemsType == wxClientData_Void )
505 oldData = GetClientData(N);
506 else if ( m_clientDataItemsType == wxClientData_Object )
507 oldObjData = GetClientObject(N);
508
509 // delete and recreate it
510 SendMessage(GetHwnd(), LB_DELETESTRING, N, 0);
511
512 int newN = N;
513 if ( N == m_noItems - 1 )
514 newN = -1;
515
516 ListBox_InsertString(GetHwnd(), newN, s);
517
518 // restore the client data
519 if ( oldData )
520 SetClientData(N, oldData);
521 else if ( oldObjData )
522 SetClientObject(N, oldObjData);
523
524 // we may have lost the selection
525 if ( wasSelected )
526 Select(N);
527
528#if wxUSE_OWNER_DRAWN
529 if ( m_windowStyle & wxLB_OWNERDRAW )
530 {
531 // update item's text
532 m_aItems[N]->SetName(s);
533
534 // reassign the item's data
535 ListBox_SetItemData(GetHwnd(), N, m_aItems[N]);
536 }
537#endif //USE_OWNER_DRAWN
538}
539
540int wxListBox::GetCount() const
541{
542 return m_noItems;
543}
544
545// ----------------------------------------------------------------------------
546// helpers
547// ----------------------------------------------------------------------------
548
549// Windows-specific code to set the horizontal extent of the listbox, if
550// necessary. If s is non-NULL, it's used to calculate the horizontal extent.
551// Otherwise, all strings are used.
552void wxListBox::SetHorizontalExtent(const wxString& s)
553{
554 // Only necessary if we want a horizontal scrollbar
555 if (!(m_windowStyle & wxHSCROLL))
556 return;
557 TEXTMETRIC lpTextMetric;
558
559 if ( !s.IsEmpty() )
560 {
561 int existingExtent = (int)SendMessage(GetHwnd(), LB_GETHORIZONTALEXTENT, 0, 0L);
562 HDC dc = GetWindowDC(GetHwnd());
563 HFONT oldFont = 0;
564 if (GetFont().Ok() && GetFont().GetResourceHandle())
565 oldFont = (HFONT) ::SelectObject(dc, (HFONT) GetFont().GetResourceHandle());
566
567 GetTextMetrics(dc, &lpTextMetric);
568 SIZE extentXY;
569 ::GetTextExtentPoint(dc, (LPTSTR) (const wxChar *)s, s.Length(), &extentXY);
570 int extentX = (int)(extentXY.cx + lpTextMetric.tmAveCharWidth);
571
572 if (oldFont)
573 ::SelectObject(dc, oldFont);
574
575 ReleaseDC(GetHwnd(), dc);
576 if (extentX > existingExtent)
577 SendMessage(GetHwnd(), LB_SETHORIZONTALEXTENT, LOWORD(extentX), 0L);
578 }
579 else
580 {
581 int largestExtent = 0;
582 HDC dc = GetWindowDC(GetHwnd());
583 HFONT oldFont = 0;
584 if (GetFont().Ok() && GetFont().GetResourceHandle())
585 oldFont = (HFONT) ::SelectObject(dc, (HFONT) GetFont().GetResourceHandle());
586
587 GetTextMetrics(dc, &lpTextMetric);
588 int i;
589 for (i = 0; i < m_noItems; i++)
590 {
591 int len = (int)SendMessage(GetHwnd(), LB_GETTEXT, i, (LONG)wxBuffer);
592 wxBuffer[len] = 0;
593 SIZE extentXY;
594 ::GetTextExtentPoint(dc, (LPTSTR)wxBuffer, len, &extentXY);
595 int extentX = (int)(extentXY.cx + lpTextMetric.tmAveCharWidth);
596 if (extentX > largestExtent)
597 largestExtent = extentX;
598 }
599 if (oldFont)
600 ::SelectObject(dc, oldFont);
601
602 ReleaseDC(GetHwnd(), dc);
603 SendMessage(GetHwnd(), LB_SETHORIZONTALEXTENT, LOWORD(largestExtent), 0L);
604 }
605}
606
607wxSize wxListBox::DoGetBestSize() const
608{
609 // find the widest string
610 int wLine;
611 int wListbox = 0;
612 for ( int i = 0; i < m_noItems; i++ )
613 {
614 wxString str(GetString(i));
615 GetTextExtent(str, &wLine, NULL);
616 if ( wLine > wListbox )
617 wListbox = wLine;
618 }
619
620 // give it some reasonable default value if there are no strings in the
621 // list
622 if ( wListbox == 0 )
623 wListbox = 100;
624
625 // the listbox should be slightly larger than the widest string
626 int cx, cy;
627 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
628
629 wListbox += 3*cx;
630
631 // don't make the listbox too tall (limit height to 10 items) but don't
632 // make it too small neither
633 int hListbox = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)*
634 wxMin(wxMax(m_noItems, 3), 10);
635
636 return wxSize(wListbox, hListbox);
637}
638
639// ----------------------------------------------------------------------------
640// callbacks
641// ----------------------------------------------------------------------------
642
643bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
644{
645 wxEventType evtType;
646 if ( param == LBN_SELCHANGE )
647 {
648 evtType = wxEVT_COMMAND_LISTBOX_SELECTED;
649 }
650 else if ( param == LBN_DBLCLK )
651 {
652 evtType = wxEVT_COMMAND_LISTBOX_DOUBLECLICKED;
653 }
654 else
655 {
656 // some event we're not interested in
657 return FALSE;
658 }
659
660 wxCommandEvent event(evtType, m_windowId);
661 event.SetEventObject( this );
662
663 // retrieve the affected item
664 int n = SendMessage(GetHwnd(), LB_GETCARETINDEX, 0, 0);
665 if ( n != LB_ERR )
666 {
667 if ( HasClientObjectData() )
668 event.SetClientObject( GetClientObject(n) );
669 else if ( HasClientUntypedData() )
670 event.SetClientData( GetClientData(n) );
671
672 event.SetString( GetString(n) );
673 event.SetExtraLong( HasMultipleSelection() ? IsSelected(n) : TRUE );
674 }
675
676 event.m_commandInt = n;
677
678 return GetEventHandler()->ProcessEvent(event);
679}
680
681// ----------------------------------------------------------------------------
682// wxCheckListBox support
683// ----------------------------------------------------------------------------
684
685#if wxUSE_OWNER_DRAWN
686
687// drawing
688// -------
689
690// space beneath/above each row in pixels
691// "standard" checklistbox use 1 here, some might prefer 2. 0 is ugly.
692#define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1)
693
694// the height is the same for all items
695// TODO should be changed for LBS_OWNERDRAWVARIABLE style listboxes
696
697// NB: can't forward this to wxListBoxItem because LB_SETITEMDATA
698// message is not yet sent when we get here!
699bool wxListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
700{
701 // only owner-drawn control should receive this message
702 wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE );
703
704 MEASUREITEMSTRUCT *pStruct = (MEASUREITEMSTRUCT *)item;
705
706 HDC hdc = CreateIC(wxT("DISPLAY"), NULL, NULL, 0);
707
708 wxDC dc;
709 dc.SetHDC((WXHDC)hdc);
710 dc.SetFont(wxSystemSettings::GetFont(wxSYS_ANSI_VAR_FONT));
711
712 pStruct->itemHeight = dc.GetCharHeight() + 2*OWNER_DRAWN_LISTBOX_EXTRA_SPACE;
713 pStruct->itemWidth = dc.GetCharWidth();
714
715 dc.SetHDC(0);
716
717 DeleteDC(hdc);
718
719 return TRUE;
720}
721
722// forward the message to the appropriate item
723bool wxListBox::MSWOnDraw(WXDRAWITEMSTRUCT *item)
724{
725 // only owner-drawn control should receive this message
726 wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE );
727
728 DRAWITEMSTRUCT *pStruct = (DRAWITEMSTRUCT *)item;
729 UINT itemID = pStruct->itemID;
730
731 // the item may be -1 for an empty listbox
732 if ( itemID == (UINT)-1 )
733 return FALSE;
734
735 long data = ListBox_GetItemData(GetHwnd(), pStruct->itemID);
736
737 wxCHECK( data && (data != LB_ERR), FALSE );
738
739 wxListBoxItem *pItem = (wxListBoxItem *)data;
740
741 wxDCTemp dc((WXHDC)pStruct->hDC);
742 wxRect rect(wxPoint(pStruct->rcItem.left, pStruct->rcItem.top),
743 wxPoint(pStruct->rcItem.right, pStruct->rcItem.bottom));
744
745 return pItem->OnDrawItem(dc, rect,
746 (wxOwnerDrawn::wxODAction)pStruct->itemAction,
747 (wxOwnerDrawn::wxODStatus)pStruct->itemState);
748}
749
750#endif // wxUSE_OWNER_DRAWN
751
752#endif // wxUSE_LISTBOX