]> git.saurik.com Git - wxWidgets.git/blob - src/msw/listctrl.cpp
TWIN32 compatibility added; wxMotif uses wxGTK's wxPostScriptDC;
[wxWidgets.git] / src / msw / listctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: listctrl.cpp
3 // Purpose: wxListCtrl
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "listctrl.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/wx.h"
25 #endif
26
27 #if defined(__WIN95__)
28
29 #include "wx/listctrl.h"
30 #include "wx/log.h"
31
32 #include "wx/msw/private.h"
33
34 #if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__)
35 #include <commctrl.h>
36 #endif
37
38 #ifndef __TWIN32__
39 #ifdef __GNUWIN32__
40 #include "wx/msw/gnuwin32/extra.h"
41 #endif
42 #endif
43
44 static void wxConvertToMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& tvItem);
45 static void wxConvertFromMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& tvItem, HWND getFullInfo = 0);
46
47 #if !USE_SHARED_LIBRARY
48 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
49 IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
50
51 #endif
52
53 wxListCtrl::wxListCtrl(void)
54 {
55 m_imageListNormal = NULL;
56 m_imageListSmall = NULL;
57 m_imageListState = NULL;
58 m_baseStyle = 0;
59 m_colCount = 0;
60 m_textCtrl = NULL;
61 }
62
63 bool wxListCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
64 long style, const wxValidator& validator, const wxString& name)
65 {
66 m_imageListNormal = NULL;
67 m_imageListSmall = NULL;
68 m_imageListState = NULL;
69 m_textCtrl = NULL;
70 m_colCount = 0;
71
72 SetValidator(validator);
73 SetName(name);
74
75 int x = pos.x;
76 int y = pos.y;
77 int width = size.x;
78 int height = size.y;
79
80 m_windowStyle = style;
81
82 SetParent(parent);
83
84 if (width <= 0)
85 width = 100;
86 if (height <= 0)
87 height = 30;
88 if (x < 0)
89 x = 0;
90 if (y < 0)
91 y = 0;
92
93 m_windowId = (id == -1) ? NewControlId() : id;
94
95 DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP;
96
97 bool want3D;
98 WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
99
100 // Even with extended styles, need to combine with WS_BORDER
101 // for them to look right.
102 if ( want3D || wxStyleHasBorder(m_windowStyle) )
103 wstyle |= WS_BORDER;
104
105 wstyle |= LVS_SHAREIMAGELISTS | LVS_SHOWSELALWAYS ;
106 m_baseStyle = wstyle;
107
108 long oldStyle = 0; // Dummy
109 wstyle |= ConvertToMSWStyle(oldStyle, m_windowStyle);
110
111 // Create the ListView control.
112 m_hWnd = (WXHWND)CreateWindowEx(exStyle,
113 WC_LISTVIEW,
114 "",
115 wstyle,
116 x, y, width, height,
117 (HWND) parent->GetHWND(),
118 (HMENU)m_windowId,
119 wxGetInstance(),
120 NULL);
121
122 if ( !m_hWnd ) {
123 wxLogError("Can't create list control window.");
124
125 return FALSE;
126 }
127
128 wxSystemSettings settings;
129 SetBackgroundColour(settings.GetSystemColour(wxSYS_COLOUR_WINDOW));
130 SetForegroundColour(parent->GetForegroundColour());
131
132 if (parent) parent->AddChild(this);
133
134 SubclassWin((WXHWND) m_hWnd);
135
136 return TRUE;
137 }
138
139 wxListCtrl::~wxListCtrl(void)
140 {
141 if (m_textCtrl)
142 {
143 m_textCtrl->UnsubclassWin();
144 m_textCtrl->SetHWND(0);
145 delete m_textCtrl;
146 m_textCtrl = NULL;
147 }
148 }
149
150 // Add or remove a single window style
151 void wxListCtrl::SetSingleStyle(long style, bool add)
152 {
153 long flag = GetWindowStyleFlag();
154
155 // Get rid of conflicting styles
156 if ( add )
157 {
158 if ( style & wxLC_MASK_TYPE)
159 flag = flag & ~wxLC_MASK_TYPE ;
160 if ( style & wxLC_MASK_ALIGN )
161 flag = flag & ~wxLC_MASK_ALIGN ;
162 if ( style & wxLC_MASK_SORT )
163 flag = flag & ~wxLC_MASK_SORT ;
164 }
165
166 if ( flag & style )
167 {
168 if ( !add )
169 flag -= style;
170 }
171 else
172 {
173 if ( add )
174 {
175 flag |= style;
176 }
177 }
178
179 m_windowStyle = flag;
180
181 RecreateWindow();
182 }
183
184 // Set the whole window style
185 void wxListCtrl::SetWindowStyleFlag(long flag)
186 {
187 m_windowStyle = flag;
188
189 RecreateWindow();
190 }
191
192 void wxListCtrl::RecreateWindow(void)
193 {
194 if ( GetHWND() )
195 {
196 long oldStyle = 0;
197 long style = ConvertToMSWStyle(oldStyle, m_windowStyle);
198 style |= m_baseStyle;
199 // ::SetWindowLong((HWND) GetHWND(), GWL_STYLE, style);
200
201 // The following recreation of the window appears to be necessary
202 // because SetWindowLong doesn't seem to do it.
203
204 int x, y, width, height;
205 GetPosition(&x, &y);
206 GetSize(&width, &height);
207
208 UnsubclassWin();
209 ::DestroyWindow((HWND) GetHWND());
210
211 // Experimental
212 // Recreate the ListView control: unfortunately I can't
213 // make it work by using SetWindowLong.
214 bool want3D;
215 WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
216 HWND hWndListControl = CreateWindowEx(exStyle,
217 WC_LISTVIEW,
218 "",
219 style,
220 x, y, width, height,
221 (HWND) GetParent()->GetHWND(),
222 (HMENU)m_windowId,
223 wxGetInstance(),
224 NULL );
225
226 m_hWnd = (WXHWND) hWndListControl;
227 SubclassWin((WXHWND) m_hWnd);
228
229 if ( m_imageListNormal )
230 SetImageList(m_imageListNormal, wxIMAGE_LIST_NORMAL);
231 if ( m_imageListSmall )
232 SetImageList(m_imageListSmall, wxIMAGE_LIST_SMALL);
233 if ( m_imageListState )
234 SetImageList(m_imageListState, wxIMAGE_LIST_STATE);
235 }
236 }
237
238 // Can be just a single style, or a bitlist
239 long wxListCtrl::ConvertToMSWStyle(long& oldStyle, long style) const
240 {
241 long wstyle = 0;
242 if ( style & wxLC_ICON )
243 {
244 if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON )
245 oldStyle -= LVS_SMALLICON;
246 if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT )
247 oldStyle -= LVS_REPORT;
248 if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST )
249 oldStyle -= LVS_LIST;
250 wstyle |= LVS_ICON;
251 }
252
253 if ( style & wxLC_SMALL_ICON )
254 {
255 if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON )
256 oldStyle -= LVS_ICON;
257 if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT )
258 oldStyle -= LVS_REPORT;
259 if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST )
260 oldStyle -= LVS_LIST;
261 wstyle |= LVS_SMALLICON;
262 }
263
264 if ( style & wxLC_LIST )
265 {
266 if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON )
267 oldStyle -= LVS_ICON;
268 if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT )
269 oldStyle -= LVS_REPORT;
270 if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON )
271 oldStyle -= LVS_SMALLICON;
272 wstyle |= LVS_LIST;
273 }
274
275 if ( style & wxLC_REPORT )
276 {
277 if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON )
278 oldStyle -= LVS_ICON;
279 if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST )
280 oldStyle -= LVS_LIST;
281 if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON )
282 oldStyle -= LVS_SMALLICON;
283 wstyle |= LVS_REPORT;
284 }
285
286 if ( style & wxLC_ALIGN_LEFT )
287 {
288 if ( oldStyle & LVS_ALIGNTOP )
289 oldStyle -= LVS_ALIGNTOP;
290 wstyle |= LVS_ALIGNLEFT;
291 }
292
293 if ( style & wxLC_ALIGN_TOP )
294 {
295 if ( oldStyle & LVS_ALIGNLEFT )
296 oldStyle -= LVS_ALIGNLEFT;
297 wstyle |= LVS_ALIGNTOP;
298 }
299
300 if ( style & wxLC_AUTOARRANGE )
301 wstyle |= LVS_AUTOARRANGE;
302
303 // Apparently, no such style (documentation wrong?)
304 /*
305 if ( style & wxLC_BUTTON )
306 wstyle |= LVS_BUTTON;
307 */
308
309 if ( style & wxLC_NO_SORT_HEADER )
310 wstyle |= LVS_NOSORTHEADER;
311
312 if ( style & wxLC_NO_HEADER )
313 wstyle |= LVS_NOCOLUMNHEADER;
314
315 if ( style & wxLC_EDIT_LABELS )
316 wstyle |= LVS_EDITLABELS;
317
318 if ( style & wxLC_SINGLE_SEL )
319 wstyle |= LVS_SINGLESEL;
320
321 if ( style & wxLC_SORT_ASCENDING )
322 {
323 if ( oldStyle & LVS_SORTDESCENDING )
324 oldStyle -= LVS_SORTDESCENDING;
325 wstyle |= LVS_SORTASCENDING;
326 }
327
328 if ( style & wxLC_SORT_DESCENDING )
329 {
330 if ( oldStyle & LVS_SORTASCENDING )
331 oldStyle -= LVS_SORTASCENDING;
332 wstyle |= LVS_SORTDESCENDING;
333 }
334
335 return wstyle;
336 }
337
338 // Sets the background colour (GetBackgroundColour already implicit in
339 // wxWindow class)
340 void wxListCtrl::SetBackgroundColour(const wxColour& col)
341 {
342 wxWindow::SetBackgroundColour(col);
343
344 ListView_SetBkColor((HWND) GetHWND(), PALETTERGB(col.Red(), col.Green(), col.Blue()));
345 }
346
347 // Gets information about this column
348 bool wxListCtrl::GetColumn(int col, wxListItem& item) const
349 {
350 LV_COLUMN lvCol;
351 lvCol.mask = 0;
352 lvCol.fmt = 0;
353 lvCol.pszText = NULL;
354
355 if ( item.m_mask & wxLIST_MASK_TEXT )
356 {
357 lvCol.mask |= LVCF_TEXT;
358 lvCol.pszText = new char[513];
359 lvCol.cchTextMax = 512;
360 }
361
362 bool success = (ListView_GetColumn((HWND) GetHWND(), col, & lvCol) != 0);
363
364 // item.m_subItem = lvCol.iSubItem;
365 item.m_width = lvCol.cx;
366
367 if ( (item.m_mask & wxLIST_MASK_TEXT) && lvCol.pszText )
368 {
369 item.m_text = lvCol.pszText;
370 delete[] lvCol.pszText;
371 }
372
373 if ( item.m_mask & wxLIST_MASK_FORMAT )
374 {
375 if (lvCol.fmt == LVCFMT_LEFT)
376 item.m_format = wxLIST_FORMAT_LEFT;
377 else if (lvCol.fmt == LVCFMT_RIGHT)
378 item.m_format = wxLIST_FORMAT_RIGHT;
379 else if (lvCol.fmt == LVCFMT_CENTER)
380 item.m_format = wxLIST_FORMAT_CENTRE;
381 }
382
383 return success;
384 }
385
386 // Sets information about this column
387 bool wxListCtrl::SetColumn(int col, wxListItem& item)
388 {
389 LV_COLUMN lvCol;
390 lvCol.mask = 0;
391 lvCol.fmt = 0;
392 lvCol.pszText = NULL;
393
394 if ( item.m_mask & wxLIST_MASK_TEXT )
395 {
396 lvCol.mask |= LVCF_TEXT;
397 lvCol.pszText = WXSTRINGCAST item.m_text;
398 lvCol.cchTextMax = 0; // Ignored
399 }
400 if ( item.m_mask & wxLIST_MASK_FORMAT )
401 {
402 lvCol.mask |= LVCF_FMT;
403
404 if ( item.m_format == wxLIST_FORMAT_LEFT )
405 lvCol.fmt = LVCFMT_LEFT;
406 if ( item.m_format == wxLIST_FORMAT_RIGHT )
407 lvCol.fmt = LVCFMT_RIGHT;
408 if ( item.m_format == wxLIST_FORMAT_CENTRE )
409 lvCol.fmt = LVCFMT_CENTER;
410 }
411
412 if ( item.m_mask & wxLIST_MASK_WIDTH )
413 {
414 lvCol.mask |= LVCF_WIDTH;
415 lvCol.cx = item.m_width;
416
417 if ( lvCol.cx == wxLIST_AUTOSIZE)
418 lvCol.cx = LVSCW_AUTOSIZE;
419 else if ( lvCol.cx == wxLIST_AUTOSIZE_USEHEADER)
420 lvCol.cx = LVSCW_AUTOSIZE_USEHEADER;
421 }
422 lvCol.mask |= LVCF_SUBITEM;
423 lvCol.iSubItem = col;
424 return (ListView_SetColumn((HWND) GetHWND(), col, & lvCol) != 0);
425 }
426
427 // Gets the column width
428 int wxListCtrl::GetColumnWidth(int col) const
429 {
430 return ListView_GetColumnWidth((HWND) GetHWND(), col);
431 }
432
433 // Sets the column width
434 bool wxListCtrl::SetColumnWidth(int col, int width)
435 {
436 int col2 = col;
437 if ( m_windowStyle & wxLC_LIST )
438 col2 = -1;
439
440 int width2 = width;
441 if ( width2 == wxLIST_AUTOSIZE)
442 width2 = LVSCW_AUTOSIZE;
443 else if ( width2 == wxLIST_AUTOSIZE_USEHEADER)
444 width2 = LVSCW_AUTOSIZE_USEHEADER;
445
446 return (ListView_SetColumnWidth((HWND) GetHWND(), col2, width2) != 0);
447 }
448
449 // Gets the number of items that can fit vertically in the
450 // visible area of the list control (list or report view)
451 // or the total number of items in the list control (icon
452 // or small icon view)
453 int wxListCtrl::GetCountPerPage(void) const
454 {
455 return ListView_GetCountPerPage((HWND) GetHWND());
456 }
457
458 // Gets the edit control for editing labels.
459 wxTextCtrl* wxListCtrl::GetEditControl(void) const
460 {
461 return m_textCtrl;
462 }
463
464 // Gets information about the item
465 bool wxListCtrl::GetItem(wxListItem& info) const
466 {
467 LV_ITEM lvItem;
468 #ifdef __MINGW32__
469 memset(&lvItem, 0, sizeof(lvItem));
470 #else
471 ZeroMemory(&lvItem, sizeof(lvItem)); // must set all fields to 0
472 #endif
473
474 lvItem.iItem = info.m_itemId;
475
476 if ( info.m_mask & wxLIST_MASK_TEXT )
477 {
478 lvItem.mask |= LVIF_TEXT;
479 lvItem.pszText = new char[513];
480 lvItem.cchTextMax = 512;
481 }
482 else
483 {
484 lvItem.pszText = NULL;
485 }
486
487 if (info.m_mask & wxLIST_MASK_DATA)
488 lvItem.mask |= LVIF_PARAM ;
489
490 if ( info.m_mask & wxLIST_MASK_STATE )
491 {
492 lvItem.mask |= LVIF_STATE;
493 // the other bits are hardly interesting anyhow
494 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
495 }
496
497 bool success = ListView_GetItem((HWND)GetHWND(), &lvItem) != 0;
498 if ( !success )
499 {
500 wxLogError(_("Couldn't retrieve information about list control item %d."),
501 lvItem.iItem);
502 }
503 else
504 {
505 wxConvertFromMSWListItem(this, info, lvItem);
506 }
507
508 if (lvItem.pszText)
509 delete[] lvItem.pszText;
510
511 return success;
512 }
513
514 // Sets information about the item
515 bool wxListCtrl::SetItem(wxListItem& info)
516 {
517 LV_ITEM item;
518 wxConvertToMSWListItem(this, info, item);
519 item.cchTextMax = 0;
520 return (ListView_SetItem((HWND) GetHWND(), &item) != 0);
521 }
522
523 long wxListCtrl::SetItem(long index, int col, const wxString& label, int imageId)
524 {
525 wxListItem info;
526 info.m_text = label;
527 info.m_mask = wxLIST_MASK_TEXT;
528 info.m_itemId = index;
529 info.m_col = col;
530 if ( imageId > -1 )
531 {
532 info.m_image = imageId;
533 info.m_mask |= wxLIST_MASK_IMAGE;
534 }
535 return SetItem(info);
536 }
537
538
539 // Gets the item state
540 int wxListCtrl::GetItemState(long item, long stateMask) const
541 {
542 wxListItem info;
543
544 info.m_mask = wxLIST_MASK_STATE ;
545 info.m_stateMask = stateMask;
546 info.m_itemId = item;
547
548 if (!GetItem(info))
549 return 0;
550
551 return info.m_state;
552 }
553
554 // Sets the item state
555 bool wxListCtrl::SetItemState(long item, long state, long stateMask)
556 {
557 wxListItem info;
558
559 info.m_mask = wxLIST_MASK_STATE ;
560 info.m_state = state;
561 info.m_stateMask = stateMask;
562 info.m_itemId = item;
563
564 return SetItem(info);
565 }
566
567 // Sets the item image
568 bool wxListCtrl::SetItemImage(long item, int image, int selImage)
569 {
570 wxListItem info;
571
572 info.m_mask = wxLIST_MASK_IMAGE ;
573 info.m_image = image;
574 info.m_itemId = item;
575
576 return SetItem(info);
577 }
578
579 // Gets the item text
580 wxString wxListCtrl::GetItemText(long item) const
581 {
582 wxListItem info;
583
584 info.m_mask = wxLIST_MASK_TEXT ;
585 info.m_itemId = item;
586
587 if (!GetItem(info))
588 return wxString("");
589 return info.m_text;
590 }
591
592 // Sets the item text
593 void wxListCtrl::SetItemText(long item, const wxString& str)
594 {
595 wxListItem info;
596
597 info.m_mask = wxLIST_MASK_TEXT ;
598 info.m_itemId = item;
599 info.m_text = str;
600
601 SetItem(info);
602 }
603
604 // Gets the item data
605 long wxListCtrl::GetItemData(long item) const
606 {
607 wxListItem info;
608
609 info.m_mask = wxLIST_MASK_DATA ;
610 info.m_itemId = item;
611
612 if (!GetItem(info))
613 return 0;
614 return info.m_data;
615 }
616
617 // Sets the item data
618 bool wxListCtrl::SetItemData(long item, long data)
619 {
620 wxListItem info;
621
622 info.m_mask = wxLIST_MASK_DATA ;
623 info.m_itemId = item;
624 info.m_data = data;
625
626 return SetItem(info);
627 }
628
629 // Gets the item rectangle
630 bool wxListCtrl::GetItemRect(long item, wxRect& rect, int code) const
631 {
632 RECT rect2;
633
634 int code2 = LVIR_BOUNDS;
635 if ( code == wxLIST_RECT_BOUNDS )
636 code2 = LVIR_BOUNDS;
637 else if ( code == wxLIST_RECT_ICON )
638 code2 = LVIR_ICON;
639 else if ( code == wxLIST_RECT_LABEL )
640 code2 = LVIR_LABEL;
641
642 bool success = (ListView_GetItemRect((HWND) GetHWND(), (int) item, &rect2, code2) != 0);
643
644 rect.x = rect2.left;
645 rect.y = rect2.top;
646 rect.width = rect2.right - rect2.left;
647 rect.height = rect2.bottom - rect2.left;
648 return success;
649 }
650
651 // Gets the item position
652 bool wxListCtrl::GetItemPosition(long item, wxPoint& pos) const
653 {
654 POINT pt;
655
656 bool success = (ListView_GetItemPosition((HWND) GetHWND(), (int) item, &pt) != 0);
657
658 pos.x = pt.x; pos.y = pt.y;
659 return success;
660 }
661
662 // Sets the item position.
663 bool wxListCtrl::SetItemPosition(long item, const wxPoint& pos)
664 {
665 return (ListView_SetItemPosition((HWND) GetHWND(), (int) item, pos.x, pos.y) != 0);
666 }
667
668 // Gets the number of items in the list control
669 int wxListCtrl::GetItemCount(void) const
670 {
671 return ListView_GetItemCount((HWND) GetHWND());
672 }
673
674 // Retrieves the spacing between icons in pixels.
675 // If small is TRUE, gets the spacing for the small icon
676 // view, otherwise the large icon view.
677 int wxListCtrl::GetItemSpacing(bool isSmall) const
678 {
679 return ListView_GetItemSpacing((HWND) GetHWND(), (BOOL) isSmall);
680 }
681
682 // Gets the number of selected items in the list control
683 int wxListCtrl::GetSelectedItemCount(void) const
684 {
685 return ListView_GetSelectedCount((HWND) GetHWND());
686 }
687
688 // Gets the text colour of the listview
689 wxColour wxListCtrl::GetTextColour(void) const
690 {
691 COLORREF ref = ListView_GetTextColor((HWND) GetHWND());
692 wxColour col(GetRValue(ref), GetGValue(ref), GetBValue(ref));
693 return col;
694 }
695
696 // Sets the text colour of the listview
697 void wxListCtrl::SetTextColour(const wxColour& col)
698 {
699 ListView_SetTextColor((HWND) GetHWND(), PALETTERGB(col.Red(), col.Blue(), col.Green()));
700 }
701
702 // Gets the index of the topmost visible item when in
703 // list or report view
704 long wxListCtrl::GetTopItem(void) const
705 {
706 return (long) ListView_GetTopIndex((HWND) GetHWND());
707 }
708
709 // Searches for an item, starting from 'item'.
710 // 'geometry' is one of
711 // wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
712 // 'state' is a state bit flag, one or more of
713 // wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
714 // item can be -1 to find the first item that matches the
715 // specified flags.
716 // Returns the item or -1 if unsuccessful.
717 long wxListCtrl::GetNextItem(long item, int geom, int state) const
718 {
719 long flags = 0;
720
721 if ( geom == wxLIST_NEXT_ABOVE )
722 flags |= LVNI_ABOVE;
723 if ( geom == wxLIST_NEXT_ALL )
724 flags |= LVNI_ALL;
725 if ( geom == wxLIST_NEXT_BELOW )
726 flags |= LVNI_BELOW;
727 if ( geom == wxLIST_NEXT_LEFT )
728 flags |= LVNI_TOLEFT;
729 if ( geom == wxLIST_NEXT_RIGHT )
730 flags |= LVNI_TORIGHT;
731
732 if ( state & wxLIST_STATE_CUT )
733 flags |= LVNI_CUT;
734 if ( state & wxLIST_STATE_DROPHILITED )
735 flags |= LVNI_DROPHILITED;
736 if ( state & wxLIST_STATE_FOCUSED )
737 flags |= LVNI_FOCUSED;
738 if ( state & wxLIST_STATE_SELECTED )
739 flags |= LVNI_SELECTED;
740
741 return (long) ListView_GetNextItem((HWND) GetHWND(), item, flags);
742 }
743
744
745 wxImageList *wxListCtrl::GetImageList(int which) const
746 {
747 if ( which == wxIMAGE_LIST_NORMAL )
748 {
749 return m_imageListNormal;
750 }
751 else if ( which == wxIMAGE_LIST_SMALL )
752 {
753 return m_imageListSmall;
754 }
755 else if ( which == wxIMAGE_LIST_STATE )
756 {
757 return m_imageListState;
758 }
759 return NULL;
760 }
761
762 void wxListCtrl::SetImageList(wxImageList *imageList, int which)
763 {
764 int flags = 0;
765 if ( which == wxIMAGE_LIST_NORMAL )
766 {
767 flags = LVSIL_NORMAL;
768 m_imageListNormal = imageList;
769 }
770 else if ( which == wxIMAGE_LIST_SMALL )
771 {
772 flags = LVSIL_SMALL;
773 m_imageListSmall = imageList;
774 }
775 else if ( which == wxIMAGE_LIST_STATE )
776 {
777 flags = LVSIL_STATE;
778 m_imageListState = imageList;
779 }
780 ListView_SetImageList((HWND) GetHWND(), (HIMAGELIST) imageList ? imageList->GetHIMAGELIST() : 0, flags);
781 }
782
783 // Operations
784 ////////////////////////////////////////////////////////////////////////////
785
786 // Arranges the items
787 bool wxListCtrl::Arrange(int flag)
788 {
789 UINT code = 0;
790 if ( flag == wxLIST_ALIGN_LEFT )
791 code = LVA_ALIGNLEFT;
792 else if ( flag == wxLIST_ALIGN_TOP )
793 code = LVA_ALIGNTOP;
794 else if ( flag == wxLIST_ALIGN_DEFAULT )
795 code = LVA_DEFAULT;
796 else if ( flag == wxLIST_ALIGN_SNAP_TO_GRID )
797 code = LVA_SNAPTOGRID;
798
799 return (ListView_Arrange((HWND) GetHWND(), code) != 0);
800 }
801
802 // Deletes an item
803 bool wxListCtrl::DeleteItem(long item)
804 {
805 return (ListView_DeleteItem((HWND) GetHWND(), (int) item) != 0);
806 }
807
808 // Deletes all items
809 bool wxListCtrl::DeleteAllItems(void)
810 {
811 return (ListView_DeleteAllItems((HWND) GetHWND()) != 0);
812 }
813
814 // Deletes all items
815 bool wxListCtrl::DeleteAllColumns(void)
816 {
817 int i;
818 for ( i = 0; i < m_colCount; i++)
819 {
820 if (ListView_DeleteColumn((HWND) GetHWND(), 0) != 0)
821 m_colCount --;
822 }
823 return (m_colCount == 0);
824 }
825
826 // Deletes a column
827 bool wxListCtrl::DeleteColumn(int col)
828 {
829 bool success = (ListView_DeleteColumn((HWND) GetHWND(), col) != 0);
830
831 if ( success && (m_colCount > 0) )
832 m_colCount --;
833 return success;
834 }
835
836 // Clears items, and columns if there are any.
837 void wxListCtrl::ClearAll(void)
838 {
839 DeleteAllItems();
840 if ( m_colCount > 0 )
841 DeleteAllColumns();
842 }
843
844 wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass)
845 {
846 wxASSERT( (textControlClass->IsKindOf(CLASSINFO(wxTextCtrl))) );
847
848 HWND hWnd = (HWND) ListView_EditLabel((HWND) GetHWND(), item);
849
850 if (m_textCtrl)
851 {
852 m_textCtrl->UnsubclassWin();
853 m_textCtrl->SetHWND(0);
854 delete m_textCtrl;
855 m_textCtrl = NULL;
856 }
857
858 m_textCtrl = (wxTextCtrl*) textControlClass->CreateObject();
859 m_textCtrl->SetHWND((WXHWND) hWnd);
860 m_textCtrl->SubclassWin((WXHWND) hWnd);
861
862 return m_textCtrl;
863 }
864
865 // End label editing, optionally cancelling the edit
866 bool wxListCtrl::EndEditLabel(bool cancel)
867 {
868 wxFAIL;
869
870 /* I don't know how to implement this: there's no such macro as ListView_EndEditLabelNow.
871 * ???
872 bool success = (ListView_EndEditLabelNow((HWND) GetHWND(), cancel) != 0);
873
874 if (m_textCtrl)
875 {
876 m_textCtrl->UnsubclassWin();
877 m_textCtrl->SetHWND(0);
878 delete m_textCtrl;
879 m_textCtrl = NULL;
880 }
881 return success;
882 */
883 return FALSE;
884 }
885
886
887 // Ensures this item is visible
888 bool wxListCtrl::EnsureVisible(long item)
889 {
890 return (ListView_EnsureVisible((HWND) GetHWND(), (int) item, FALSE) != 0);
891 }
892
893 // Find an item whose label matches this string, starting from the item after 'start'
894 // or the beginning if 'start' is -1.
895 long wxListCtrl::FindItem(long start, const wxString& str, bool partial)
896 {
897 LV_FINDINFO findInfo;
898
899 findInfo.flags = LVFI_STRING;
900 if ( partial )
901 findInfo.flags |= LVFI_STRING;
902 findInfo.psz = WXSTRINGCAST str;
903
904 return ListView_FindItem((HWND) GetHWND(), (int) start, & findInfo);
905 }
906
907 // Find an item whose data matches this data, starting from the item after 'start'
908 // or the beginning if 'start' is -1.
909 long wxListCtrl::FindItem(long start, long data)
910 {
911 LV_FINDINFO findInfo;
912
913 findInfo.flags = LVFI_PARAM;
914 findInfo.lParam = data;
915
916 return ListView_FindItem((HWND) GetHWND(), (int) start, & findInfo);
917 }
918
919 // Find an item nearest this position in the specified direction, starting from
920 // the item after 'start' or the beginning if 'start' is -1.
921 long wxListCtrl::FindItem(long start, const wxPoint& pt, int direction)
922 {
923 LV_FINDINFO findInfo;
924
925 findInfo.flags = LVFI_NEARESTXY;
926 findInfo.pt.x = pt.x;
927 findInfo.pt.y = pt.y;
928 findInfo.vkDirection = VK_RIGHT;
929
930 if ( direction == wxLIST_FIND_UP )
931 findInfo.vkDirection = VK_UP;
932 else if ( direction == wxLIST_FIND_DOWN )
933 findInfo.vkDirection = VK_DOWN;
934 else if ( direction == wxLIST_FIND_LEFT )
935 findInfo.vkDirection = VK_LEFT;
936 else if ( direction == wxLIST_FIND_RIGHT )
937 findInfo.vkDirection = VK_RIGHT;
938
939 return ListView_FindItem((HWND) GetHWND(), (int) start, & findInfo);
940 }
941
942 // Determines which item (if any) is at the specified point,
943 // giving details in 'flags' (see wxLIST_HITTEST_... flags above)
944 long wxListCtrl::HitTest(const wxPoint& point, int& flags)
945 {
946 LV_HITTESTINFO hitTestInfo;
947 hitTestInfo.pt.x = (int) point.x;
948 hitTestInfo.pt.y = (int) point.y;
949
950 ListView_HitTest((HWND) GetHWND(), & hitTestInfo);
951
952 flags = 0;
953 if ( hitTestInfo.flags & LVHT_ABOVE )
954 flags |= wxLIST_HITTEST_ABOVE;
955 if ( hitTestInfo.flags & LVHT_BELOW )
956 flags |= wxLIST_HITTEST_BELOW;
957 if ( hitTestInfo.flags & LVHT_NOWHERE )
958 flags |= wxLIST_HITTEST_NOWHERE;
959 if ( hitTestInfo.flags & LVHT_ONITEMICON )
960 flags |= wxLIST_HITTEST_ONITEMICON;
961 if ( hitTestInfo.flags & LVHT_ONITEMLABEL )
962 flags |= wxLIST_HITTEST_ONITEMLABEL;
963 if ( hitTestInfo.flags & LVHT_ONITEMSTATEICON )
964 flags |= wxLIST_HITTEST_ONITEMSTATEICON;
965 if ( hitTestInfo.flags & LVHT_TOLEFT )
966 flags |= wxLIST_HITTEST_TOLEFT;
967 if ( hitTestInfo.flags & LVHT_TORIGHT )
968 flags |= wxLIST_HITTEST_TORIGHT;
969
970 return (long) hitTestInfo.iItem ;
971 }
972
973 // Inserts an item, returning the index of the new item if successful,
974 // -1 otherwise.
975 long wxListCtrl::InsertItem(wxListItem& info)
976 {
977 LV_ITEM item;
978 wxConvertToMSWListItem(this, info, item);
979
980 return (long) ListView_InsertItem((HWND) GetHWND(), & item);
981 }
982
983 long wxListCtrl::InsertItem(long index, const wxString& label)
984 {
985 wxListItem info;
986 info.m_text = label;
987 info.m_mask = wxLIST_MASK_TEXT;
988 info.m_itemId = index;
989 return InsertItem(info);
990 }
991
992 // Inserts an image item
993 long wxListCtrl::InsertItem(long index, int imageIndex)
994 {
995 wxListItem info;
996 info.m_image = imageIndex;
997 info.m_mask = wxLIST_MASK_IMAGE;
998 info.m_itemId = index;
999 return InsertItem(info);
1000 }
1001
1002 // Inserts an image/string item
1003 long wxListCtrl::InsertItem(long index, const wxString& label, int imageIndex)
1004 {
1005 wxListItem info;
1006 info.m_image = imageIndex;
1007 info.m_text = label;
1008 info.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
1009 info.m_itemId = index;
1010 return InsertItem(info);
1011 }
1012
1013 // For list view mode (only), inserts a column.
1014 long wxListCtrl::InsertColumn(long col, wxListItem& item)
1015 {
1016 LV_COLUMN lvCol;
1017 lvCol.mask = 0;
1018 lvCol.fmt = 0;
1019 lvCol.pszText = NULL;
1020
1021 if ( item.m_mask & wxLIST_MASK_TEXT )
1022 {
1023 lvCol.mask |= LVCF_TEXT;
1024 lvCol.pszText = WXSTRINGCAST item.m_text;
1025 lvCol.cchTextMax = 0; // Ignored
1026 }
1027 if ( item.m_mask & wxLIST_MASK_FORMAT )
1028 {
1029 lvCol.mask |= LVCF_FMT;
1030
1031 if ( item.m_format == wxLIST_FORMAT_LEFT )
1032 lvCol.fmt = LVCFMT_LEFT;
1033 if ( item.m_format == wxLIST_FORMAT_RIGHT )
1034 lvCol.fmt = LVCFMT_RIGHT;
1035 if ( item.m_format == wxLIST_FORMAT_CENTRE )
1036 lvCol.fmt = LVCFMT_CENTER;
1037 }
1038
1039 if ( item.m_mask & wxLIST_MASK_WIDTH )
1040 {
1041 lvCol.mask |= LVCF_WIDTH;
1042 lvCol.cx = item.m_width;
1043
1044 if ( lvCol.cx == wxLIST_AUTOSIZE)
1045 lvCol.cx = LVSCW_AUTOSIZE;
1046 else if ( lvCol.cx == wxLIST_AUTOSIZE_USEHEADER)
1047 lvCol.cx = LVSCW_AUTOSIZE_USEHEADER;
1048 }
1049 lvCol.mask |= LVCF_SUBITEM;
1050 lvCol.iSubItem = col;
1051
1052 bool success = (ListView_InsertColumn((HWND) GetHWND(), col, & lvCol) != 0);
1053 if ( success )
1054 m_colCount ++;
1055 return success;
1056 }
1057
1058 long wxListCtrl::InsertColumn(long col, const wxString& heading, int format,
1059 int width)
1060 {
1061 wxListItem item;
1062 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
1063 item.m_text = heading;
1064 if ( width > -1 )
1065 {
1066 item.m_mask |= wxLIST_MASK_WIDTH;
1067 item.m_width = width;
1068 }
1069 item.m_format = format;
1070
1071 return InsertColumn(col, item);
1072 }
1073
1074 // Scrolls the list control. If in icon, small icon or report view mode,
1075 // x specifies the number of pixels to scroll. If in list view mode, x
1076 // specifies the number of columns to scroll.
1077 // If in icon, small icon or list view mode, y specifies the number of pixels
1078 // to scroll. If in report view mode, y specifies the number of lines to scroll.
1079 bool wxListCtrl::ScrollList(int dx, int dy)
1080 {
1081 return (ListView_Scroll((HWND) GetHWND(), dx, dy) != 0);
1082 }
1083
1084 // Sort items.
1085
1086 // fn is a function which takes 3 long arguments: item1, item2, data.
1087 // item1 is the long data associated with a first item (NOT the index).
1088 // item2 is the long data associated with a second item (NOT the index).
1089 // data is the same value as passed to SortItems.
1090 // The return value is a negative number if the first item should precede the second
1091 // item, a positive number of the second item should precede the first,
1092 // or zero if the two items are equivalent.
1093
1094 // data is arbitrary data to be passed to the sort function.
1095 bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data)
1096 {
1097 return (ListView_SortItems((HWND) GetHWND(), (PFNLVCOMPARE) fn, data) != 0);
1098 }
1099
1100 bool wxListCtrl::MSWCommand(WXUINT cmd, WXWORD id)
1101 {
1102 if (cmd == EN_UPDATE)
1103 {
1104 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id);
1105 event.SetEventObject( this );
1106 ProcessCommand(event);
1107 return TRUE;
1108 }
1109 else if (cmd == EN_KILLFOCUS)
1110 {
1111 wxCommandEvent event(wxEVT_KILL_FOCUS, id);
1112 event.SetEventObject( this );
1113 ProcessCommand(event);
1114 return TRUE;
1115 }
1116 else return FALSE;
1117 }
1118
1119 bool wxListCtrl::MSWNotify(WXWPARAM wParam, WXLPARAM lParam, WXLPARAM *result)
1120 {
1121 wxListEvent event(wxEVT_NULL, m_windowId);
1122 wxEventType eventType = wxEVT_NULL;
1123 NMHDR *hdr1 = (NMHDR *) lParam;
1124 switch ( hdr1->code )
1125 {
1126 case LVN_BEGINRDRAG:
1127 eventType = wxEVT_COMMAND_LIST_BEGIN_RDRAG;
1128 // fall through
1129
1130 case LVN_BEGINDRAG:
1131 if ( eventType == wxEVT_NULL )
1132 {
1133 eventType = wxEVT_COMMAND_LIST_BEGIN_DRAG;
1134 }
1135
1136 {
1137 NM_LISTVIEW *hdr = (NM_LISTVIEW *)lParam;
1138 event.m_itemIndex = hdr->iItem;
1139 event.m_pointDrag.x = hdr->ptAction.x;
1140 event.m_pointDrag.y = hdr->ptAction.y;
1141 }
1142 break;
1143
1144 case LVN_BEGINLABELEDIT:
1145 {
1146 eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
1147 LV_DISPINFO *info = (LV_DISPINFO *)lParam;
1148 wxConvertFromMSWListItem(this, event.m_item, info->item, (HWND) GetHWND());
1149 break;
1150 }
1151
1152 case LVN_COLUMNCLICK:
1153 {
1154 eventType = wxEVT_COMMAND_LIST_COL_CLICK;
1155 NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
1156 event.m_itemIndex = -1;
1157 event.m_col = hdr->iSubItem;
1158 break;
1159 }
1160 case LVN_DELETEALLITEMS:
1161 {
1162 eventType = wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS;
1163 // NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
1164 event.m_itemIndex = -1;
1165 break;
1166 }
1167 case LVN_DELETEITEM:
1168 {
1169 eventType = wxEVT_COMMAND_LIST_DELETE_ITEM;
1170 NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
1171 event.m_itemIndex = hdr->iItem;
1172 break;
1173 }
1174 case LVN_ENDLABELEDIT:
1175 {
1176 eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
1177 LV_DISPINFO *info = (LV_DISPINFO *)lParam;
1178 wxConvertFromMSWListItem(this, event.m_item, info->item, (HWND) GetHWND());
1179 if ( info->item.pszText == NULL || info->item.iItem == -1 )
1180 event.m_cancelled = TRUE;
1181 break;
1182 }
1183 case LVN_GETDISPINFO:
1184 {
1185 // return FALSE;
1186 // TODO: some text buffering here, I think
1187 // TODO: API for getting Windows to retrieve values
1188 // on demand.
1189 eventType = wxEVT_COMMAND_LIST_GET_INFO;
1190 LV_DISPINFO *info = (LV_DISPINFO *)lParam;
1191 wxConvertFromMSWListItem(this, event.m_item, info->item, (HWND) GetHWND());
1192 break;
1193 }
1194 case LVN_INSERTITEM:
1195 {
1196 eventType = wxEVT_COMMAND_LIST_INSERT_ITEM;
1197 NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
1198 event.m_itemIndex = hdr->iItem;
1199 break;
1200 }
1201 case LVN_ITEMCHANGED:
1202 {
1203 // This needs to be sent to wxListCtrl as a rather more
1204 // concrete event. For now, just detect a selection
1205 // or deselection.
1206 NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
1207 if ( (hdr->uNewState & LVIS_SELECTED) && !(hdr->uOldState & LVIS_SELECTED) )
1208 {
1209 eventType = wxEVT_COMMAND_LIST_ITEM_SELECTED;
1210 event.m_itemIndex = hdr->iItem;
1211 }
1212 else if ( !(hdr->uNewState & LVIS_SELECTED) && (hdr->uOldState & LVIS_SELECTED) )
1213 {
1214 eventType = wxEVT_COMMAND_LIST_ITEM_DESELECTED;
1215 event.m_itemIndex = hdr->iItem;
1216 }
1217 else
1218 return FALSE;
1219 break;
1220 }
1221 case LVN_KEYDOWN:
1222 {
1223 eventType = wxEVT_COMMAND_LIST_KEY_DOWN;
1224 LV_KEYDOWN *info = (LV_KEYDOWN *)lParam;
1225 event.m_code = wxCharCodeMSWToWX(info->wVKey);
1226 break;
1227 }
1228 case LVN_SETDISPINFO:
1229 {
1230 eventType = wxEVT_COMMAND_LIST_SET_INFO;
1231 LV_DISPINFO *info = (LV_DISPINFO *)lParam;
1232 wxConvertFromMSWListItem(this, event.m_item, info->item, (HWND) GetHWND());
1233 break;
1234 }
1235
1236 default :
1237 return wxControl::MSWNotify(wParam, lParam, result);
1238 }
1239
1240 event.SetEventObject( this );
1241 event.SetEventType(eventType);
1242
1243 if ( !GetEventHandler()->ProcessEvent(event) )
1244 return FALSE;
1245
1246 if (hdr1->code == LVN_GETDISPINFO)
1247 {
1248 LV_DISPINFO *info = (LV_DISPINFO *)lParam;
1249 if ( info->item.mask & LVIF_TEXT )
1250 {
1251 if ( !event.m_item.m_text.IsNull() )
1252 {
1253 info->item.pszText = AddPool(event.m_item.m_text);
1254 info->item.cchTextMax = strlen(info->item.pszText) + 1;
1255 }
1256 }
1257 // wxConvertToMSWListItem(this, event.m_item, info->item);
1258 }
1259
1260 *result = !event.IsAllowed();
1261
1262 return TRUE;
1263 }
1264
1265 char *wxListCtrl::AddPool(const wxString& str)
1266 {
1267 // Remove the first element if 3 strings exist
1268 if ( m_stringPool.Number() == 3 )
1269 {
1270 wxNode *node = m_stringPool.First();
1271 delete[] (char *)node->Data();
1272 delete node;
1273 }
1274 wxNode *node = m_stringPool.Add((char *) (const char *)str);
1275 return (char *)node->Data();
1276 }
1277
1278 // List item structure
1279 wxListItem::wxListItem(void)
1280 {
1281 m_mask = 0;
1282 m_itemId = 0;
1283 m_col = 0;
1284 m_state = 0;
1285 m_stateMask = 0;
1286 m_image = 0;
1287 m_data = 0;
1288
1289 m_format = wxLIST_FORMAT_CENTRE;
1290 m_width = 0;
1291 }
1292
1293 static void wxConvertFromMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& lvItem, HWND getFullInfo)
1294 {
1295 info.m_data = lvItem.lParam;
1296 info.m_mask = 0;
1297 info.m_state = 0;
1298 info.m_stateMask = 0;
1299 info.m_itemId = lvItem.iItem;
1300
1301 long oldMask = lvItem.mask;
1302
1303 bool needText = FALSE;
1304 if (getFullInfo != 0)
1305 {
1306 if ( lvItem.mask & LVIF_TEXT )
1307 needText = FALSE;
1308 else
1309 needText = TRUE;
1310
1311 if ( needText )
1312 {
1313 lvItem.pszText = new char[513];
1314 lvItem.cchTextMax = 512;
1315 }
1316 // lvItem.mask |= TVIF_HANDLE | TVIF_STATE | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM ;
1317 lvItem.mask |= LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM ;
1318 ::SendMessage(getFullInfo, LVM_GETITEM, 0, (LPARAM)& lvItem) ;
1319 }
1320
1321 if ( lvItem.mask & LVIF_STATE )
1322 {
1323 info.m_mask |= wxLIST_MASK_STATE;
1324
1325 if ( lvItem.stateMask & LVIS_CUT)
1326 {
1327 info.m_stateMask |= wxLIST_STATE_CUT ;
1328 if ( lvItem.state & LVIS_CUT )
1329 info.m_state |= wxLIST_STATE_CUT ;
1330 }
1331 if ( lvItem.stateMask & LVIS_DROPHILITED)
1332 {
1333 info.m_stateMask |= wxLIST_STATE_DROPHILITED ;
1334 if ( lvItem.state & LVIS_DROPHILITED )
1335 info.m_state |= wxLIST_STATE_DROPHILITED ;
1336 }
1337 if ( lvItem.stateMask & LVIS_FOCUSED)
1338 {
1339 info.m_stateMask |= wxLIST_STATE_FOCUSED ;
1340 if ( lvItem.state & LVIS_FOCUSED )
1341 info.m_state |= wxLIST_STATE_FOCUSED ;
1342 }
1343 if ( lvItem.stateMask & LVIS_SELECTED)
1344 {
1345 info.m_stateMask |= wxLIST_STATE_SELECTED ;
1346 if ( lvItem.state & LVIS_SELECTED )
1347 info.m_state |= wxLIST_STATE_SELECTED ;
1348 }
1349 }
1350
1351 if ( lvItem.mask & LVIF_TEXT )
1352 {
1353 info.m_mask |= wxLIST_MASK_TEXT;
1354 info.m_text = lvItem.pszText;
1355 }
1356 if ( lvItem.mask & LVIF_IMAGE )
1357 {
1358 info.m_mask |= wxLIST_MASK_IMAGE;
1359 info.m_image = lvItem.iImage;
1360 }
1361 if ( lvItem.mask & LVIF_PARAM )
1362 info.m_mask |= wxLIST_MASK_DATA;
1363 if ( lvItem.mask & LVIF_DI_SETITEM )
1364 info.m_mask |= wxLIST_SET_ITEM;
1365 info.m_col = lvItem.iSubItem;
1366
1367 if (needText)
1368 {
1369 if (lvItem.pszText)
1370 delete[] lvItem.pszText;
1371 }
1372 lvItem.mask = oldMask ;
1373 }
1374
1375 static void wxConvertToMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& lvItem)
1376 {
1377 lvItem.iItem = (int) info.m_itemId ;
1378
1379 lvItem.iImage = info.m_image ;
1380 lvItem.lParam = info.m_data;
1381 lvItem.stateMask = 0;
1382 lvItem.state = 0;
1383 lvItem.mask = 0;
1384 lvItem.iSubItem = info.m_col;
1385
1386 if (info.m_mask & wxLIST_MASK_STATE)
1387 {
1388 lvItem.mask |= LVIF_STATE ;
1389 if (info.m_stateMask & wxLIST_STATE_CUT)
1390 {
1391 lvItem.stateMask |= LVIS_CUT ;
1392 if (info.m_state & wxLIST_STATE_CUT)
1393 lvItem.state |= LVIS_CUT;
1394 }
1395 if (info.m_stateMask & wxLIST_STATE_DROPHILITED)
1396 {
1397 lvItem.stateMask |= LVIS_DROPHILITED;
1398 if (info.m_state & wxLIST_STATE_DROPHILITED)
1399 lvItem.state |= LVIS_DROPHILITED;
1400 }
1401 if (info.m_stateMask & wxLIST_STATE_FOCUSED)
1402 {
1403 lvItem.stateMask |= LVIS_FOCUSED;
1404 if (info.m_state & wxLIST_STATE_FOCUSED)
1405 lvItem.state |= LVIS_FOCUSED;
1406 }
1407 if (info.m_stateMask & wxLIST_STATE_SELECTED)
1408 {
1409 lvItem.stateMask |= LVIS_SELECTED;
1410 if (info.m_state & wxLIST_STATE_SELECTED)
1411 lvItem.state |= LVIS_SELECTED;
1412 }
1413 }
1414
1415 if (info.m_mask & wxLIST_MASK_TEXT)
1416 {
1417 lvItem.mask |= LVIF_TEXT ;
1418 if ( ctrl->GetWindowStyleFlag() & wxLC_USER_TEXT )
1419 {
1420 lvItem.pszText = LPSTR_TEXTCALLBACK;
1421 }
1422 else
1423 {
1424 lvItem.pszText = (char *) (const char *)info.m_text ;
1425 if ( lvItem.pszText )
1426 lvItem.cchTextMax = info.m_text.Length();
1427 else
1428 lvItem.cchTextMax = 0;
1429 }
1430 }
1431 if (info.m_mask & wxLIST_MASK_IMAGE)
1432 lvItem.mask |= LVIF_IMAGE ;
1433 if (info.m_mask & wxLIST_MASK_DATA)
1434 lvItem.mask |= LVIF_PARAM ;
1435 }
1436
1437 // List event
1438 IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
1439
1440 wxListEvent::wxListEvent(wxEventType commandType, int id)
1441 : wxNotifyEvent(commandType, id)
1442 {
1443 m_code = 0;
1444 m_itemIndex = 0;
1445 m_col = 0;
1446 m_cancelled = FALSE;
1447 }
1448
1449 #endif
1450