]> git.saurik.com Git - wxWidgets.git/blob - src/msw/listbox.cpp
GetSelections() changed to work with wxArrayInt
[wxWidgets.git] / src / msw / listbox.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: 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 license
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 #ifndef WX_PRECOMP
24 #include "wx/listbox.h"
25 #include "wx/settings.h"
26 #endif
27
28 #include "wx/msw/private.h"
29
30 #include <windows.h>
31 #include <windowsx.h>
32
33 #ifdef __GNUWIN32__
34 #include <wx/msw/gnuwin32/extra.h>
35 #endif
36
37 #ifdef GetCharWidth
38 #undef GetCharWidth
39 #endif
40
41 #if USE_OWNER_DRAWN
42 #include "wx/ownerdrw.h"
43 #endif
44
45 #include "wx/dynarray.h"
46 #include "wx/log.h"
47
48 #if !USE_SHARED_LIBRARY
49 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
50 #endif
51
52 // ============================================================================
53 // list box item declaration and implementation
54 // ============================================================================
55
56 #if USE_OWNER_DRAWN
57
58 class wxListBoxItem : public wxOwnerDrawn
59 {
60 public:
61 wxListBoxItem(const wxString& str = "");
62 };
63
64 wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE)
65 {
66 // no bitmaps/checkmarks
67 SetMarginWidth(0);
68 }
69
70 wxOwnerDrawn *wxListBox::CreateItem(uint n)
71 {
72 return new wxListBoxItem();
73 }
74
75 #endif //USE_OWNER_DRAWN
76
77 // ============================================================================
78 // list box control implementation
79 // ============================================================================
80
81 // this macro is dangerous but still better than tons of (HWND)GetHWND()
82 #define hwnd (HWND)GetHWND()
83
84 bool wxListBox::MSWCommand(const WXUINT param, const WXWORD WXUNUSED(id))
85 {
86 /*
87 if (param == LBN_SELCANCEL)
88 {
89 event.extraLong = FALSE;
90 }
91 */
92 if (param == LBN_SELCHANGE)
93 {
94 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
95 wxArrayInt aSelections;
96 int count = GetSelections(aSelections);
97 if ( count > 0 )
98 {
99 event.m_commandInt = aSelections[0] ;
100 event.m_clientData = GetClientData(event.m_commandInt);
101 wxString str(GetString(event.m_commandInt));
102 if (str != "")
103 event.m_commandString = copystring((char *)(const char *)str);
104 }
105 else
106 {
107 event.m_commandInt = -1 ;
108 event.m_commandString = copystring("") ;
109 }
110
111 event.SetEventObject( this );
112 ProcessCommand(event);
113 if (event.m_commandString)
114 delete[] event.m_commandString ;
115 return TRUE;
116 }
117 else if (param == LBN_DBLCLK)
118 {
119 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
120 event.SetEventObject( this );
121 if ( !GetEventHandler()->ProcessEvent(event) )
122 {
123 #if WXWIN_COMPATIBILITY
124 wxWindow *parent = (wxWindow *)GetParent();
125 if (parent)
126 parent->GetEventHandler()->OnDefaultAction(this);
127 #endif
128 return TRUE;
129 }
130 }
131 return FALSE;
132 }
133
134 // Listbox item
135 wxListBox::wxListBox(void)
136 {
137 m_noItems = 0;
138 m_selected = 0;
139 }
140
141 bool wxListBox::Create(wxWindow *parent, const wxWindowID id,
142 const wxPoint& pos,
143 const wxSize& size,
144 const int n, const wxString choices[],
145 const long style,
146 const wxValidator& validator,
147 const wxString& name)
148 {
149 m_noItems = n;
150 m_hWnd = 0;
151 m_selected = 0;
152
153 SetName(name);
154 SetValidator(validator);
155
156 if (parent) parent->AddChild(this);
157
158 wxSystemSettings settings;
159 SetBackgroundColour(settings.GetSystemColour(wxSYS_COLOUR_WINDOW));
160 SetForegroundColour(parent->GetDefaultForegroundColour());
161
162 m_windowId = ( id == -1 ) ? (int)NewControlId() : id;
163
164 int x = pos.x;
165 int y = pos.y;
166 int width = size.x;
167 int height = size.y;
168 m_windowStyle = style;
169
170 DWORD wstyle = WS_VSCROLL | WS_TABSTOP | LBS_NOTIFY | LBS_HASSTRINGS;
171 if (m_windowStyle & wxLB_MULTIPLE)
172 wstyle |= LBS_MULTIPLESEL;
173 else if (m_windowStyle & wxLB_EXTENDED)
174 wstyle |= LBS_EXTENDEDSEL;
175
176 if (m_windowStyle & wxLB_ALWAYS_SB)
177 wstyle |= LBS_DISABLENOSCROLL ;
178 if (m_windowStyle & wxLB_HSCROLL)
179 wstyle |= WS_HSCROLL;
180 if (m_windowStyle & wxLB_SORT)
181 wstyle |= LBS_SORT;
182
183 #if USE_OWNER_DRAWN
184 if ( m_windowStyle & wxLB_OWNERDRAW ) {
185 // we don't support LBS_OWNERDRAWVARIABLE yet
186 wstyle |= LBS_OWNERDRAWFIXED;
187 }
188 #endif
189 // Without this style, you get unexpected heights, so e.g. constraint layout
190 // doesn't work properly
191 wstyle |= LBS_NOINTEGRALHEIGHT;
192
193 bool want3D;
194 WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
195
196 // Even with extended styles, need to combine with WS_BORDER
197 // for them to look right.
198 if ( want3D || (m_windowStyle & wxSIMPLE_BORDER)
199 || (m_windowStyle & wxRAISED_BORDER)
200 || (m_windowStyle & wxSUNKEN_BORDER)
201 || (m_windowStyle & wxDOUBLE_BORDER) ) {
202 wstyle |= WS_BORDER;
203 }
204
205 HWND wx_list = CreateWindowEx(exStyle, "LISTBOX", NULL,
206 wstyle | WS_CHILD,
207 0, 0, 0, 0,
208 (HWND)parent->GetHWND(), (HMENU)m_windowId,
209 wxGetInstance(), NULL);
210 #if CTL3D
211 if (want3D)
212 {
213 Ctl3dSubclassCtl(wx_list);
214 m_useCtl3D = TRUE;
215 }
216 #endif
217
218 uint ui;
219 for (ui = 0; ui < (uint)n; ui++) {
220 SendMessage(wx_list, LB_ADDSTRING, 0, (LPARAM)(const char *)choices[ui]);
221 }
222
223 #if USE_OWNER_DRAWN
224 if ( m_windowStyle & wxLB_OWNERDRAW ) {
225 for (ui = 0; ui < (uint)n; ui++) {
226 // create new item which will process WM_{DRAW|MEASURE}ITEM messages
227 wxOwnerDrawn *pNewItem = CreateItem(ui);
228 pNewItem->SetName(choices[ui]);
229 m_aItems.Add(pNewItem);
230 ListBox_SetItemData(wx_list, ui, pNewItem);
231 }
232 }
233 #endif
234
235 if ((m_windowStyle & wxLB_MULTIPLE) == 0)
236 SendMessage(wx_list, LB_SETCURSEL, 0, 0);
237
238 ShowWindow(wx_list, SW_SHOW);
239
240 m_hWnd = (WXHWND)wx_list;
241
242 // Subclass again for purposes of dialog editing mode
243 SubclassWin((WXHWND)wx_list);
244
245 SetFont(* parent->GetFont());
246
247 SetSize(x, y, width, height);
248
249 return TRUE;
250 }
251
252 wxListBox::~wxListBox(void)
253 {
254 #if USE_OWNER_DRAWN
255 uint uiCount = m_aItems.Count();
256 while ( uiCount-- != 0 ) {
257 delete m_aItems[uiCount];
258 }
259 #endif
260 }
261
262 void wxListBox::SetupColours(void)
263 {
264 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW));
265 SetForegroundColour(GetParent()->GetDefaultForegroundColour());
266 }
267
268 void wxListBox::SetFirstItem(const int N)
269 {
270 SendMessage(hwnd,LB_SETTOPINDEX,(WPARAM)N,(LPARAM)0) ;
271 }
272
273 void wxListBox::SetFirstItem(const wxString& s)
274 {
275 int N = FindString(s) ;
276
277 if (N>=0)
278 SetFirstItem(N) ;
279 }
280
281 void wxListBox::Delete(const int N)
282 {
283 SendMessage(hwnd, LB_DELETESTRING, N, 0);
284 m_noItems --;
285 SetHorizontalExtent("");
286 }
287
288 void wxListBox::Append(const wxString& item)
289 {
290 int index = ListBox_AddString(hwnd, item);
291 m_noItems ++;
292
293 #if USE_OWNER_DRAWN
294 if ( m_windowStyle & wxLB_OWNERDRAW ) {
295 wxOwnerDrawn *pNewItem = CreateItem(-1); // dummy argument
296 pNewItem->SetName(item);
297 m_aItems.Add(pNewItem);
298 ListBox_SetItemData(hwnd, index, pNewItem);
299 }
300 #endif
301
302 SetHorizontalExtent(item);
303 }
304
305 void wxListBox::Append(const wxString& item, char *Client_data)
306 {
307 int index = ListBox_AddString(hwnd, item);
308 m_noItems ++;
309
310 #if USE_OWNER_DRAWN
311 if ( m_windowStyle & wxLB_OWNERDRAW ) {
312 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
313 // in OnMeasure/OnDraw.
314 wxFAIL_MSG("Can't use client data with owner-drawn listboxes");
315 }
316 else
317 #endif
318 ListBox_SetItemData(hwnd, index, Client_data);
319
320 SetHorizontalExtent(item);
321 }
322
323 void wxListBox::Set(const int n, const wxString *choices, char** clientData)
324 {
325 ShowWindow(hwnd, SW_HIDE);
326 ListBox_ResetContent(hwnd);
327 int i;
328 for (i = 0; i < n; i++)
329 {
330 ListBox_AddString(hwnd, choices[i]);
331 if ( clientData )
332 ListBox_SetItemData(hwnd, i, clientData[i]);
333 }
334 m_noItems = n;
335
336 #if USE_OWNER_DRAWN
337 if ( m_windowStyle & wxLB_OWNERDRAW ) {
338 // first delete old items
339 uint ui = m_aItems.Count();
340 while ( ui-- != 0 ) {
341 delete m_aItems[ui];
342 }
343 m_aItems.Empty();
344
345 // then create new ones
346 for (ui = 0; ui < (uint)n; ui++) {
347 wxOwnerDrawn *pNewItem = CreateItem(ui);
348 pNewItem->SetName(choices[ui]);
349 m_aItems.Add(pNewItem);
350 ListBox_SetItemData(hwnd, ui, pNewItem);
351
352 wxASSERT_MSG(clientData[ui] == NULL,
353 "Can't use client data with owner-drawn listboxes");
354 }
355 }
356 #endif
357
358 SetHorizontalExtent("");
359 ShowWindow(hwnd, SW_SHOW);
360 }
361
362 int wxListBox::FindString(const wxString& s) const
363 {
364 int pos = ListBox_FindStringExact(hwnd, (WPARAM)-1, s);
365 if (pos == LB_ERR)
366 return -1;
367 else
368 return pos;
369 }
370
371 void wxListBox::Clear(void)
372 {
373 ListBox_ResetContent(hwnd);
374
375 m_noItems = 0;
376 ListBox_GetHorizontalExtent(hwnd);
377 }
378
379 void wxListBox::SetSelection(const int N, const bool select)
380 {
381 if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED))
382 SendMessage(hwnd, LB_SETSEL, select, N);
383 else
384 {
385 int N1 = N;
386 if (!select)
387 N1 = -1;
388 SendMessage(hwnd, LB_SETCURSEL, N1, 0);
389 }
390 }
391
392 bool wxListBox::Selected(const int N) const
393 {
394 return SendMessage(hwnd, LB_GETSEL, N, 0) == 0 ? FALSE : TRUE;
395 }
396
397 void wxListBox::Deselect(const int N)
398 {
399 if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED))
400 SendMessage(hwnd, LB_SETSEL, FALSE, N);
401 }
402
403 char *wxListBox::GetClientData(const int N) const
404 {
405 return (char *)SendMessage(hwnd, LB_GETITEMDATA, N, 0);
406 }
407
408 void wxListBox::SetClientData(const int N, char *Client_data)
409 {
410 if ( ListBox_SetItemData(hwnd, N, Client_data) == LB_ERR )
411 wxLogDebug("LB_SETITEMDATA failed");
412 }
413
414 // Return number of selections and an array of selected integers
415 int wxListBox::GetSelections(wxArrayInt& aSelections) const
416 {
417 aSelections.Empty();
418
419 if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED))
420 {
421 int no_sel = ListBox_GetSelCount(hwnd);
422 if (no_sel != 0) {
423 int *selections = new int[no_sel];
424 if ( ListBox_GetSelItems(hwnd, no_sel, selections) == LB_ERR ) {
425 wxFAIL_MSG("This listbox can't have single-selection style!");
426 }
427
428 aSelections.Alloc(no_sel);
429 for ( int n = 0; n < no_sel; n++ )
430 aSelections.Add(selections[n]);
431
432 delete [] selections;
433 }
434
435 return no_sel;
436 }
437 else // single-selection listbox
438 {
439 aSelections.Add(ListBox_GetCurSel(hwnd));
440
441 return 1;
442 }
443 }
444
445 // Get single selection, for single choice list items
446 int wxListBox::GetSelection() const
447 {
448 wxCHECK_MSG( !(m_windowStyle & wxLB_MULTIPLE) &&
449 !(m_windowStyle & wxLB_EXTENDED),
450 -1,
451 "GetSelection() can't be used with multiple-selection "
452 "listboxes, use GetSelections() instead." );
453
454 return ListBox_GetCurSel(hwnd);
455 }
456
457 // Find string for position
458 wxString wxListBox::GetString(const int N) const
459 {
460 if (N < 0 || N > m_noItems)
461 return wxString("");
462
463 int len = (int)SendMessage(hwnd, LB_GETTEXT, N, (LONG)wxBuffer);
464 wxBuffer[len] = 0;
465 return wxString(wxBuffer);
466 }
467
468 void wxListBox::SetSize(const int x, const int y, const int width, const int height, const int sizeFlags)
469 {
470 int currentX, currentY;
471 GetPosition(&currentX, &currentY);
472
473 int x1 = x;
474 int y1 = y;
475 int w1 = width;
476 int h1 = height;
477
478 if (x == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
479 x1 = currentX;
480 if (y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
481 y1 = currentY;
482
483 // If we're prepared to use the existing size, then...
484 if (width == -1 && height == -1 && ((sizeFlags & wxSIZE_AUTO) != wxSIZE_AUTO))
485 {
486 GetSize(&w1, &h1);
487 }
488
489 int cx; // button font dimensions
490 int cy;
491
492 wxGetCharSize(GetHWND(), &cx, &cy,GetFont());
493
494 float control_width, control_height, control_x, control_y;
495
496 // Deal with default size (using -1 values)
497 if (w1<=0)
498 w1 = DEFAULT_ITEM_WIDTH;
499
500 if (h1<=0)
501 h1 = DEFAULT_ITEM_HEIGHT;
502
503 control_x = (float)x1;
504 control_y = (float)y1;
505 control_width = (float)w1;
506 control_height = (float)h1;
507
508 // Calculations may have made size too small
509 if (control_height <= 0)
510 control_height = (float)DEFAULT_ITEM_HEIGHT;
511
512 if (control_width <= 0)
513 control_width = (float)DEFAULT_ITEM_WIDTH;
514
515 // wxDebugMsg("About to set the listbox height to %d", (int)control_height);
516 MoveWindow(hwnd, (int)control_x, (int)control_y,
517 (int)control_width, (int)control_height, TRUE);
518
519 /*
520 #if WXWIN_COMPATIBILITY
521 GetEventHandler()->OldOnSize(width, height);
522 #else
523 wxSizeEvent event(wxSize(width, height), m_windowId);
524 event.eventObject = this;
525 GetEventHandler()->ProcessEvent(event);
526 #endif
527 */
528
529 }
530
531 // Windows-specific code to set the horizontal extent of
532 // the listbox, if necessary. If s is non-NULL, it's
533 // used to calculate the horizontal extent.
534 // Otherwise, all strings are used.
535 void wxListBox::SetHorizontalExtent(const wxString& s)
536 {
537 // Only necessary if we want a horizontal scrollbar
538 if (!(m_windowStyle & wxHSCROLL))
539 return;
540 TEXTMETRIC lpTextMetric;
541
542 if (s != "")
543 {
544 int existingExtent = (int)SendMessage(hwnd, LB_GETHORIZONTALEXTENT, 0, 0L);
545 HDC dc = GetWindowDC(hwnd);
546 HFONT oldFont = 0;
547 if (GetFont() && GetFont()->GetResourceHandle())
548 oldFont = ::SelectObject(dc, (HFONT) GetFont()->GetResourceHandle());
549
550 GetTextMetrics(dc, &lpTextMetric);
551 SIZE extentXY;
552 ::GetTextExtentPoint(dc, (LPSTR) (const char *)s, s.Length(), &extentXY);
553 int extentX = (int)(extentXY.cx + lpTextMetric.tmAveCharWidth);
554
555 if (oldFont)
556 ::SelectObject(dc, oldFont);
557
558 ReleaseDC(hwnd, dc);
559 if (extentX > existingExtent)
560 SendMessage(hwnd, LB_SETHORIZONTALEXTENT, LOWORD(extentX), 0L);
561 return;
562 }
563 else
564 {
565 int largestExtent = 0;
566 HDC dc = GetWindowDC(hwnd);
567 HFONT oldFont = 0;
568 if (GetFont() && GetFont()->GetResourceHandle())
569 oldFont = ::SelectObject(dc, (HFONT) GetFont()->GetResourceHandle());
570
571 GetTextMetrics(dc, &lpTextMetric);
572 int i;
573 for (i = 0; i < m_noItems; i++)
574 {
575 int len = (int)SendMessage(hwnd, LB_GETTEXT, i, (LONG)wxBuffer);
576 wxBuffer[len] = 0;
577 SIZE extentXY;
578 ::GetTextExtentPoint(dc, (LPSTR)wxBuffer, len, &extentXY);
579 int extentX = (int)(extentXY.cx + lpTextMetric.tmAveCharWidth);
580 if (extentX > largestExtent)
581 largestExtent = extentX;
582 }
583 if (oldFont)
584 ::SelectObject(dc, oldFont);
585
586 ReleaseDC(hwnd, dc);
587 SendMessage(hwnd, LB_SETHORIZONTALEXTENT, LOWORD(largestExtent), 0L);
588 }
589 }
590
591 void
592 wxListBox::InsertItems(const int nItems, const wxString items[], const int pos)
593 {
594 int i;
595 for (i = 0; i < nItems; i++)
596 ListBox_InsertString(hwnd, i + pos, items[i]);
597 m_noItems += nItems;
598
599 #if USE_OWNER_DRAWN
600 if ( m_windowStyle & wxLB_OWNERDRAW ) {
601 for ( i = 0; i < nItems; i++ ) {
602 wxOwnerDrawn *pNewItem = CreateItem((uint)(pos + i));
603 pNewItem->SetName(items[i]);
604 m_aItems.Insert(pNewItem, (uint)(pos + i));
605 ListBox_SetItemData(hwnd, i, pNewItem);
606 }
607 }
608 #endif
609
610 SetHorizontalExtent("");
611 }
612
613 void wxListBox::SetString(const int N, const wxString& s)
614 {
615 int sel = GetSelection();
616
617 char *oldData = (char *)wxListBox::GetClientData(N);
618
619 SendMessage(hwnd, LB_DELETESTRING, N, 0);
620
621 int newN = N;
622 if (N == (m_noItems - 1))
623 newN = -1;
624
625 SendMessage(hwnd, LB_INSERTSTRING, newN, (LPARAM) (const char *)s);
626 if (oldData)
627 wxListBox::SetClientData(N, oldData);
628
629 // Selection may have changed
630 if (sel >= 0)
631 SetSelection(sel);
632
633 #if USE_OWNER_DRAWN
634 if ( m_windowStyle & wxLB_OWNERDRAW )
635 // update item's text
636 m_aItems[N]->SetName(s);
637 #endif //USE_OWNER_DRAWN
638 }
639
640 int wxListBox::Number (void) const
641 {
642 return m_noItems;
643 }
644
645 // For single selection items only
646 wxString wxListBox::GetStringSelection (void) const
647 {
648 int sel = GetSelection ();
649 if (sel > -1)
650 return this->GetString (sel);
651 else
652 return wxString("");
653 }
654
655 bool wxListBox::SetStringSelection (const wxString& s, const bool flag)
656 {
657 int sel = FindString (s);
658 if (sel > -1)
659 {
660 SetSelection (sel, flag);
661 return TRUE;
662 }
663 else
664 return FALSE;
665 }
666
667 // Is this the right thing? Won't setselection generate a command
668 // event too? No! It'll just generate a setselection event.
669 // But we still can't have this being called whenever a real command
670 // is generated, because it sets the selection, which will already
671 // have been done! (Unless we have an optional argument for calling
672 // by the actual window system, or a separate function, ProcessCommand)
673 void wxListBox::Command (wxCommandEvent & event)
674 {
675 if (event.m_extraLong)
676 SetSelection (event.m_commandInt);
677 else
678 {
679 Deselect (event.m_commandInt);
680 return;
681 }
682 ProcessCommand (event);
683 }
684
685 WXHBRUSH wxListBox::OnCtlColor(const WXHDC pDC, const WXHWND pWnd, const WXUINT nCtlColor,
686 WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
687 {
688 #if CTL3D
689 if ( m_useCtl3D )
690 {
691 HBRUSH hbrush = Ctl3dCtlColorEx(message, wParam, lParam);
692 return (WXHBRUSH) hbrush;
693 }
694 #endif
695
696 if (GetParent()->GetTransparentBackground())
697 SetBkMode((HDC) pDC, TRANSPARENT);
698 else
699 SetBkMode((HDC) pDC, OPAQUE);
700
701 ::SetBkColor((HDC) pDC, RGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue()));
702 ::SetTextColor((HDC) pDC, RGB(GetForegroundColour().Red(), GetForegroundColour().Green(), GetForegroundColour().Blue()));
703
704 wxBrush *backgroundBrush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID);
705
706 // Note that this will be cleaned up in wxApp::OnIdle, if backgroundBrush
707 // has a zero usage count.
708 backgroundBrush->RealizeResource();
709 return (WXHBRUSH) backgroundBrush->GetResourceHandle();
710 }
711
712 long wxListBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
713 {
714 /*
715 switch (nMsg)
716 {
717 case WM_INITDIALOG:
718 case WM_ACTIVATE:
719 case WM_SETFOCUS:
720 case WM_KILLFOCUS:
721 case WM_CREATE:
722 case WM_PAINT:
723 case WM_QUERYDRAGICON:
724 case WM_SIZE:
725 case WM_RBUTTONDOWN:
726 case WM_RBUTTONUP:
727 case WM_RBUTTONDBLCLK:
728 case WM_MBUTTONDOWN:
729 case WM_MBUTTONUP:
730 case WM_MBUTTONDBLCLK:
731 case WM_LBUTTONDOWN:
732 case WM_LBUTTONUP:
733 // case WM_LBUTTONDBLCLK:
734 case WM_MOUSEMOVE:
735 case WM_DESTROY:
736 case WM_COMMAND:
737 case WM_NOTIFY:
738 case WM_MENUSELECT:
739 case WM_INITMENUPOPUP:
740 case WM_DRAWITEM:
741 case WM_MEASUREITEM:
742 case WM_KEYDOWN:
743 case WM_KEYUP:
744 case WM_CHAR: // Always an ASCII character
745 case WM_HSCROLL:
746 case WM_VSCROLL:
747 case WM_CTLCOLORBTN:
748 case WM_CTLCOLORDLG:
749 case WM_CTLCOLORLISTBOX:
750 case WM_CTLCOLORMSGBOX:
751 case WM_CTLCOLORSCROLLBAR:
752 case WM_CTLCOLORSTATIC:
753 case WM_CTLCOLOREDIT:
754 case WM_SYSCOLORCHANGE:
755 case WM_ERASEBKGND:
756 case WM_MDIACTIVATE:
757 case WM_DROPFILES:
758 case WM_QUERYENDSESSION:
759 case WM_CLOSE:
760 case WM_GETMINMAXINFO:
761 case WM_NCHITTEST:
762 return MSWDefWindowProc(nMsg, wParam, lParam );
763 }
764 */
765 return wxControl::MSWWindowProc(nMsg, wParam, lParam);
766 }
767
768 #if USE_OWNER_DRAWN
769
770 // drawing
771 // -------
772
773 // space beneath/above each row in pixels
774 // "standard" checklistbox use 1 here, some might prefer 2. 0 is ugly.
775 #define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1)
776
777 // the height is the same for all items
778 // ## should be changed for LBS_OWNERDRAWVARIABLE style listboxes
779 // NB: can't forward this to wxListBoxItem because LB_SETITEMDATA
780 // message is not yet sent when we get here!
781 bool wxListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
782 {
783 // only owner-drawn control should receive this message
784 wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE );
785
786 MEASUREITEMSTRUCT *pStruct = (MEASUREITEMSTRUCT *)item;
787
788 wxDC dc;
789 dc.SetHDC((WXHDC)CreateIC("DISPLAY", NULL, NULL, 0));
790 dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_ANSI_VAR_FONT));
791
792 pStruct->itemHeight = dc.GetCharHeight() + 2*OWNER_DRAWN_LISTBOX_EXTRA_SPACE;
793 pStruct->itemWidth = dc.GetCharWidth();
794
795 return TRUE;
796 }
797
798 // forward the message to the appropriate item
799 bool wxListBox::MSWOnDraw(WXDRAWITEMSTRUCT *item)
800 {
801 // only owner-drawn control should receive this message
802 wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE );
803
804 DRAWITEMSTRUCT *pStruct = (DRAWITEMSTRUCT *)item;
805 wxListBoxItem *pItem = (wxListBoxItem *)SendMessage(hwnd, LB_GETITEMDATA,
806 pStruct->itemID, 0);
807
808 wxCHECK( (int)pItem != LB_ERR, FALSE );
809
810 wxDC dc;
811 dc.SetHDC((WXHDC)pStruct->hDC, FALSE);
812 wxRect rect(pStruct->rcItem.left, pStruct->rcItem.top,
813 pStruct->rcItem.right - pStruct->rcItem.left,
814 pStruct->rcItem.bottom - pStruct->rcItem.top);
815
816 return pItem->OnDrawItem(dc, rect,
817 (wxOwnerDrawn::wxODAction)pStruct->itemAction,
818 (wxOwnerDrawn::wxODStatus)pStruct->itemState);
819 }
820
821 #endif
822 // USE_OWNER_DRAWN