1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "listctrl.h"
22 #pragma implementation "listctrlbase.h"
25 // For compilers that support precompilation, includes "wx.h".
26 #include "wx/wxprec.h"
38 #include "wx/settings.h"
41 #include "wx/textctrl.h"
42 #include "wx/imaglist.h"
44 #include "wx/listctrl.h"
46 #include "wx/msw/private.h"
48 #ifdef __GNUWIN32_OLD__
49 #include "wx/msw/gnuwin32/extra.h"
56 (LVHT_ONITEMICON | LVHT_ONITEMLABEL | LVHT_ONITEMSTATEICON)
59 #ifndef LVM_SETEXTENDEDLISTVIEWSTYLE
60 #define LVM_SETEXTENDEDLISTVIEWSTYLE (0x1000 + 54)
63 #ifndef LVS_EX_FULLROWSELECT
64 #define LVS_EX_FULLROWSELECT 0x00000020
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
71 static void wxConvertToMSWListItem(const wxListCtrl
*ctrl
, wxListItem
& info
, LV_ITEM
& tvItem
);
72 static void wxConvertFromMSWListItem(const wxListCtrl
*ctrl
, wxListItem
& info
, LV_ITEM
& tvItem
, HWND getFullInfo
= 0);
74 // ----------------------------------------------------------------------------
76 // ----------------------------------------------------------------------------
78 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
)
79 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
)
81 // ============================================================================
83 // ============================================================================
85 // ----------------------------------------------------------------------------
87 // ----------------------------------------------------------------------------
89 void wxListEvent::CopyObject(wxObject
& object_dest
) const
91 wxListEvent
*obj
= (wxListEvent
*)&object_dest
;
93 wxNotifyEvent::CopyObject(object_dest
);
96 obj
->m_itemIndex
= m_itemIndex
;
97 obj
->m_oldItemIndex
= m_oldItemIndex
;
99 obj
->m_cancelled
= m_cancelled
;
100 obj
->m_pointDrag
= m_pointDrag
;
101 obj
->m_item
.m_mask
= m_item
.m_mask
;
102 obj
->m_item
.m_itemId
= m_item
.m_itemId
;
103 obj
->m_item
.m_col
= m_item
.m_col
;
104 obj
->m_item
.m_state
= m_item
.m_state
;
105 obj
->m_item
.m_stateMask
= m_item
.m_stateMask
;
106 obj
->m_item
.m_text
= m_item
.m_text
;
107 obj
->m_item
.m_image
= m_item
.m_image
;
108 obj
->m_item
.m_data
= m_item
.m_data
;
109 obj
->m_item
.m_format
= m_item
.m_format
;
110 obj
->m_item
.m_width
= m_item
.m_width
;
112 if ( m_item
.HasAttributes() )
114 obj
->m_item
.SetTextColour(m_item
.GetTextColour());
115 obj
->m_item
.SetBackgroundColour(m_item
.GetBackgroundColour());
116 obj
->m_item
.SetFont(m_item
.GetFont());
120 // ----------------------------------------------------------------------------
121 // wxListCtrl construction
122 // ----------------------------------------------------------------------------
124 void wxListCtrl::Init()
126 m_imageListNormal
= NULL
;
127 m_imageListSmall
= NULL
;
128 m_imageListState
= NULL
;
132 m_hasAnyAttr
= FALSE
;
135 bool wxListCtrl::Create(wxWindow
*parent
,
140 const wxValidator
& validator
,
141 const wxString
& name
)
144 SetValidator(validator
);
145 #endif // wxUSE_VALIDATORS
154 m_windowStyle
= style
;
167 m_windowId
= (id
== -1) ? NewControlId() : id
;
169 DWORD wstyle
= WS_VISIBLE
| WS_CHILD
| WS_TABSTOP
|
170 LVS_SHAREIMAGELISTS
| LVS_SHOWSELALWAYS
;
171 if ( wxStyleHasBorder(m_windowStyle
) )
173 m_baseStyle
= wstyle
;
175 if ( !DoCreateControl(x
, y
, width
, height
) )
179 parent
->AddChild(this);
184 bool wxListCtrl::DoCreateControl(int x
, int y
, int w
, int h
)
186 DWORD wstyle
= m_baseStyle
;
189 WXDWORD exStyle
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
);
191 // Even with extended styles, need to combine with WS_BORDER
192 // for them to look right.
196 long oldStyle
= 0; // Dummy
197 wstyle
|= ConvertToMSWStyle(oldStyle
, m_windowStyle
);
199 // Create the ListView control.
200 m_hWnd
= (WXHWND
)CreateWindowEx(exStyle
,
205 GetWinHwnd(GetParent()),
212 wxLogError(_("Can't create list control window, check that comctl32.dll is installed."));
217 // for comctl32.dll v 4.70+ we want to have this attribute because it's
218 // prettier (and also because wxGTK does it like this)
219 if ( (wstyle
& LVS_REPORT
) && wxTheApp
->GetComCtl32Version() >= 470 )
221 ::SendMessage(GetHwnd(), LVM_SETEXTENDEDLISTVIEWSTYLE
,
222 0, LVS_EX_FULLROWSELECT
);
225 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW
));
226 SetForegroundColour(GetParent()->GetForegroundColour());
233 void wxListCtrl::UpdateStyle()
237 // The new window view style
239 DWORD dwStyleNew
= ConvertToMSWStyle(dummy
, m_windowStyle
);
240 dwStyleNew
|= m_baseStyle
;
242 // Get the current window style.
243 DWORD dwStyleOld
= ::GetWindowLong(GetHwnd(), GWL_STYLE
);
245 // Only set the window style if the view bits have changed.
246 if ( dwStyleOld
!= dwStyleNew
)
248 ::SetWindowLong(GetHwnd(), GWL_STYLE
, dwStyleNew
);
253 void wxListCtrl::FreeAllAttrs(bool dontRecreate
)
257 for ( wxNode
*node
= m_attrs
.Next(); node
; node
= m_attrs
.Next() )
259 delete (wxListItemAttr
*)node
->Data();
265 m_attrs
.Create(wxKEY_INTEGER
, 1000); // just as def ctor
268 m_hasAnyAttr
= FALSE
;
272 wxListCtrl::~wxListCtrl()
274 FreeAllAttrs(TRUE
/* no need to recreate hash any more */);
278 m_textCtrl
->UnsubclassWin();
279 m_textCtrl
->SetHWND(0);
285 // ----------------------------------------------------------------------------
286 // set/get/change style
287 // ----------------------------------------------------------------------------
289 // Add or remove a single window style
290 void wxListCtrl::SetSingleStyle(long style
, bool add
)
292 long flag
= GetWindowStyleFlag();
294 // Get rid of conflicting styles
297 if ( style
& wxLC_MASK_TYPE
)
298 flag
= flag
& ~wxLC_MASK_TYPE
;
299 if ( style
& wxLC_MASK_ALIGN
)
300 flag
= flag
& ~wxLC_MASK_ALIGN
;
301 if ( style
& wxLC_MASK_SORT
)
302 flag
= flag
& ~wxLC_MASK_SORT
;
318 m_windowStyle
= flag
;
323 // Set the whole window style
324 void wxListCtrl::SetWindowStyleFlag(long flag
)
326 m_windowStyle
= flag
;
331 // Can be just a single style, or a bitlist
332 long wxListCtrl::ConvertToMSWStyle(long& oldStyle
, long style
) const
335 if ( style
& wxLC_ICON
)
337 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_SMALLICON
)
338 oldStyle
-= LVS_SMALLICON
;
339 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_REPORT
)
340 oldStyle
-= LVS_REPORT
;
341 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_LIST
)
342 oldStyle
-= LVS_LIST
;
346 if ( style
& wxLC_SMALL_ICON
)
348 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_ICON
)
349 oldStyle
-= LVS_ICON
;
350 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_REPORT
)
351 oldStyle
-= LVS_REPORT
;
352 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_LIST
)
353 oldStyle
-= LVS_LIST
;
354 wstyle
|= LVS_SMALLICON
;
357 if ( style
& wxLC_LIST
)
359 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_ICON
)
360 oldStyle
-= LVS_ICON
;
361 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_REPORT
)
362 oldStyle
-= LVS_REPORT
;
363 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_SMALLICON
)
364 oldStyle
-= LVS_SMALLICON
;
368 if ( style
& wxLC_REPORT
)
370 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_ICON
)
371 oldStyle
-= LVS_ICON
;
372 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_LIST
)
373 oldStyle
-= LVS_LIST
;
374 if ( (oldStyle
& LVS_TYPEMASK
) == LVS_SMALLICON
)
375 oldStyle
-= LVS_SMALLICON
;
377 wstyle
|= LVS_REPORT
;
380 if ( style
& wxLC_ALIGN_LEFT
)
382 if ( oldStyle
& LVS_ALIGNTOP
)
383 oldStyle
-= LVS_ALIGNTOP
;
384 wstyle
|= LVS_ALIGNLEFT
;
387 if ( style
& wxLC_ALIGN_TOP
)
389 if ( oldStyle
& LVS_ALIGNLEFT
)
390 oldStyle
-= LVS_ALIGNLEFT
;
391 wstyle
|= LVS_ALIGNTOP
;
394 if ( style
& wxLC_AUTOARRANGE
)
395 wstyle
|= LVS_AUTOARRANGE
;
397 // Apparently, no such style (documentation wrong?)
399 if ( style & wxLC_BUTTON )
400 wstyle |= LVS_BUTTON;
403 if ( style
& wxLC_NO_SORT_HEADER
)
404 wstyle
|= LVS_NOSORTHEADER
;
406 if ( style
& wxLC_NO_HEADER
)
407 wstyle
|= LVS_NOCOLUMNHEADER
;
409 if ( style
& wxLC_EDIT_LABELS
)
410 wstyle
|= LVS_EDITLABELS
;
412 if ( style
& wxLC_SINGLE_SEL
)
413 wstyle
|= LVS_SINGLESEL
;
415 if ( style
& wxLC_SORT_ASCENDING
)
417 if ( oldStyle
& LVS_SORTDESCENDING
)
418 oldStyle
-= LVS_SORTDESCENDING
;
419 wstyle
|= LVS_SORTASCENDING
;
422 if ( style
& wxLC_SORT_DESCENDING
)
424 if ( oldStyle
& LVS_SORTASCENDING
)
425 oldStyle
-= LVS_SORTASCENDING
;
426 wstyle
|= LVS_SORTDESCENDING
;
432 // ----------------------------------------------------------------------------
434 // ----------------------------------------------------------------------------
436 // Sets the foreground, i.e. text, colour
437 bool wxListCtrl::SetForegroundColour(const wxColour
& col
)
439 if ( !wxWindow::SetForegroundColour(col
) )
442 ListView_SetTextColor(GetHwnd(), wxColourToRGB(col
));
447 // Sets the background colour
448 bool wxListCtrl::SetBackgroundColour(const wxColour
& col
)
450 if ( !wxWindow::SetBackgroundColour(col
) )
453 // we set the same colour for both the "empty" background and the items
455 COLORREF color
= wxColourToRGB(col
);
456 ListView_SetBkColor(GetHwnd(), color
);
457 ListView_SetTextBkColor(GetHwnd(), color
);
462 // Gets information about this column
463 bool wxListCtrl::GetColumn(int col
, wxListItem
& item
) const
468 lvCol
.pszText
= NULL
;
470 if ( item
.m_mask
& wxLIST_MASK_TEXT
)
472 lvCol
.mask
|= LVCF_TEXT
;
473 lvCol
.pszText
= new wxChar
[513];
474 lvCol
.cchTextMax
= 512;
477 bool success
= (ListView_GetColumn(GetHwnd(), col
, & lvCol
) != 0);
479 // item.m_subItem = lvCol.iSubItem;
480 item
.m_width
= lvCol
.cx
;
482 if ( (item
.m_mask
& wxLIST_MASK_TEXT
) && lvCol
.pszText
)
484 item
.m_text
= lvCol
.pszText
;
485 delete[] lvCol
.pszText
;
488 if ( item
.m_mask
& wxLIST_MASK_FORMAT
)
490 if (lvCol
.fmt
== LVCFMT_LEFT
)
491 item
.m_format
= wxLIST_FORMAT_LEFT
;
492 else if (lvCol
.fmt
== LVCFMT_RIGHT
)
493 item
.m_format
= wxLIST_FORMAT_RIGHT
;
494 else if (lvCol
.fmt
== LVCFMT_CENTER
)
495 item
.m_format
= wxLIST_FORMAT_CENTRE
;
501 // Sets information about this column
502 bool wxListCtrl::SetColumn(int col
, wxListItem
& item
)
507 lvCol
.pszText
= NULL
;
509 if ( item
.m_mask
& wxLIST_MASK_TEXT
)
511 lvCol
.mask
|= LVCF_TEXT
;
512 lvCol
.pszText
= WXSTRINGCAST item
.m_text
;
513 lvCol
.cchTextMax
= 0; // Ignored
515 if ( item
.m_mask
& wxLIST_MASK_FORMAT
)
517 lvCol
.mask
|= LVCF_FMT
;
519 if ( item
.m_format
== wxLIST_FORMAT_LEFT
)
520 lvCol
.fmt
= LVCFMT_LEFT
;
521 if ( item
.m_format
== wxLIST_FORMAT_RIGHT
)
522 lvCol
.fmt
= LVCFMT_RIGHT
;
523 if ( item
.m_format
== wxLIST_FORMAT_CENTRE
)
524 lvCol
.fmt
= LVCFMT_CENTER
;
527 if ( item
.m_mask
& wxLIST_MASK_WIDTH
)
529 lvCol
.mask
|= LVCF_WIDTH
;
530 lvCol
.cx
= item
.m_width
;
532 if ( lvCol
.cx
== wxLIST_AUTOSIZE
)
533 lvCol
.cx
= LVSCW_AUTOSIZE
;
534 else if ( lvCol
.cx
== wxLIST_AUTOSIZE_USEHEADER
)
535 lvCol
.cx
= LVSCW_AUTOSIZE_USEHEADER
;
537 lvCol
.mask
|= LVCF_SUBITEM
;
538 lvCol
.iSubItem
= col
;
539 return (ListView_SetColumn(GetHwnd(), col
, & lvCol
) != 0);
542 // Gets the column width
543 int wxListCtrl::GetColumnWidth(int col
) const
545 return ListView_GetColumnWidth(GetHwnd(), col
);
548 // Sets the column width
549 bool wxListCtrl::SetColumnWidth(int col
, int width
)
552 if ( m_windowStyle
& wxLC_LIST
)
556 if ( width2
== wxLIST_AUTOSIZE
)
557 width2
= LVSCW_AUTOSIZE
;
558 else if ( width2
== wxLIST_AUTOSIZE_USEHEADER
)
559 width2
= LVSCW_AUTOSIZE_USEHEADER
;
561 return (ListView_SetColumnWidth(GetHwnd(), col2
, width2
) != 0);
564 // Gets the number of items that can fit vertically in the
565 // visible area of the list control (list or report view)
566 // or the total number of items in the list control (icon
567 // or small icon view)
568 int wxListCtrl::GetCountPerPage() const
570 return ListView_GetCountPerPage(GetHwnd());
573 // Gets the edit control for editing labels.
574 wxTextCtrl
* wxListCtrl::GetEditControl() const
579 // Gets information about the item
580 bool wxListCtrl::GetItem(wxListItem
& info
) const
583 wxZeroMemory(lvItem
);
585 lvItem
.iItem
= info
.m_itemId
;
586 lvItem
.iSubItem
= info
.m_col
;
588 if ( info
.m_mask
& wxLIST_MASK_TEXT
)
590 lvItem
.mask
|= LVIF_TEXT
;
591 lvItem
.pszText
= new wxChar
[513];
592 lvItem
.cchTextMax
= 512;
596 lvItem
.pszText
= NULL
;
599 if (info
.m_mask
& wxLIST_MASK_DATA
)
600 lvItem
.mask
|= LVIF_PARAM
;
602 if ( info
.m_mask
& wxLIST_MASK_STATE
)
604 lvItem
.mask
|= LVIF_STATE
;
605 // the other bits are hardly interesting anyhow
606 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
609 bool success
= ListView_GetItem((HWND
)GetHWND(), &lvItem
) != 0;
612 wxLogError(_("Couldn't retrieve information about list control item %d."),
617 wxConvertFromMSWListItem(this, info
, lvItem
);
621 delete[] lvItem
.pszText
;
626 // Sets information about the item
627 bool wxListCtrl::SetItem(wxListItem
& info
)
630 wxConvertToMSWListItem(this, info
, item
);
632 // check whether it has any custom attributes
633 if ( info
.HasAttributes() )
635 wxListItemAttr
*attr
;
636 attr
= (wxListItemAttr
*) m_attrs
.Get(item
.iItem
);
638 m_attrs
.Put(item
.iItem
, (wxObject
*)new wxListItemAttr(*info
.GetAttributes()));
639 else *attr
= *info
.GetAttributes();
645 bool ok
= ListView_SetItem(GetHwnd(), &item
) != 0;
646 if ( ok
&& (info
.m_mask
& wxLIST_MASK_IMAGE
) )
648 // make the change visible
649 ListView_Update(GetHwnd(), item
.iItem
);
655 long wxListCtrl::SetItem(long index
, int col
, const wxString
& label
, int imageId
)
659 info
.m_mask
= wxLIST_MASK_TEXT
;
660 info
.m_itemId
= index
;
664 info
.m_image
= imageId
;
665 info
.m_mask
|= wxLIST_MASK_IMAGE
;
667 return SetItem(info
);
671 // Gets the item state
672 int wxListCtrl::GetItemState(long item
, long stateMask
) const
676 info
.m_mask
= wxLIST_MASK_STATE
;
677 info
.m_stateMask
= stateMask
;
678 info
.m_itemId
= item
;
686 // Sets the item state
687 bool wxListCtrl::SetItemState(long item
, long state
, long stateMask
)
691 info
.m_mask
= wxLIST_MASK_STATE
;
692 info
.m_state
= state
;
693 info
.m_stateMask
= stateMask
;
694 info
.m_itemId
= item
;
696 return SetItem(info
);
699 // Sets the item image
700 bool wxListCtrl::SetItemImage(long item
, int image
, int selImage
)
704 info
.m_mask
= wxLIST_MASK_IMAGE
;
705 info
.m_image
= image
;
706 info
.m_itemId
= item
;
708 return SetItem(info
);
711 // Gets the item text
712 wxString
wxListCtrl::GetItemText(long item
) const
716 info
.m_mask
= wxLIST_MASK_TEXT
;
717 info
.m_itemId
= item
;
724 // Sets the item text
725 void wxListCtrl::SetItemText(long item
, const wxString
& str
)
729 info
.m_mask
= wxLIST_MASK_TEXT
;
730 info
.m_itemId
= item
;
736 // Gets the item data
737 long wxListCtrl::GetItemData(long item
) const
741 info
.m_mask
= wxLIST_MASK_DATA
;
742 info
.m_itemId
= item
;
749 // Sets the item data
750 bool wxListCtrl::SetItemData(long item
, long data
)
754 info
.m_mask
= wxLIST_MASK_DATA
;
755 info
.m_itemId
= item
;
758 return SetItem(info
);
761 // Gets the item rectangle
762 bool wxListCtrl::GetItemRect(long item
, wxRect
& rect
, int code
) const
766 int code2
= LVIR_BOUNDS
;
767 if ( code
== wxLIST_RECT_BOUNDS
)
769 else if ( code
== wxLIST_RECT_ICON
)
771 else if ( code
== wxLIST_RECT_LABEL
)
775 bool success
= (ListView_GetItemRect(GetHwnd(), (int) item
, &rect2
) != 0);
777 bool success
= (ListView_GetItemRect(GetHwnd(), (int) item
, &rect2
, code2
) != 0);
782 rect
.width
= rect2
.right
- rect2
.left
;
783 rect
.height
= rect2
.bottom
- rect2
.top
;
787 // Gets the item position
788 bool wxListCtrl::GetItemPosition(long item
, wxPoint
& pos
) const
792 bool success
= (ListView_GetItemPosition(GetHwnd(), (int) item
, &pt
) != 0);
794 pos
.x
= pt
.x
; pos
.y
= pt
.y
;
798 // Sets the item position.
799 bool wxListCtrl::SetItemPosition(long item
, const wxPoint
& pos
)
801 return (ListView_SetItemPosition(GetHwnd(), (int) item
, pos
.x
, pos
.y
) != 0);
804 // Gets the number of items in the list control
805 int wxListCtrl::GetItemCount() const
807 return ListView_GetItemCount(GetHwnd());
810 // Retrieves the spacing between icons in pixels.
811 // If small is TRUE, gets the spacing for the small icon
812 // view, otherwise the large icon view.
813 int wxListCtrl::GetItemSpacing(bool isSmall
) const
815 return ListView_GetItemSpacing(GetHwnd(), (BOOL
) isSmall
);
818 // Gets the number of selected items in the list control
819 int wxListCtrl::GetSelectedItemCount() const
821 return ListView_GetSelectedCount(GetHwnd());
824 // Gets the text colour of the listview
825 wxColour
wxListCtrl::GetTextColour() const
827 COLORREF ref
= ListView_GetTextColor(GetHwnd());
828 wxColour
col(GetRValue(ref
), GetGValue(ref
), GetBValue(ref
));
832 // Sets the text colour of the listview
833 void wxListCtrl::SetTextColour(const wxColour
& col
)
835 ListView_SetTextColor(GetHwnd(), PALETTERGB(col
.Red(), col
.Green(), col
.Blue()));
838 // Gets the index of the topmost visible item when in
839 // list or report view
840 long wxListCtrl::GetTopItem() const
842 return (long) ListView_GetTopIndex(GetHwnd());
845 // Searches for an item, starting from 'item'.
846 // 'geometry' is one of
847 // wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
848 // 'state' is a state bit flag, one or more of
849 // wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
850 // item can be -1 to find the first item that matches the
852 // Returns the item or -1 if unsuccessful.
853 long wxListCtrl::GetNextItem(long item
, int geom
, int state
) const
857 if ( geom
== wxLIST_NEXT_ABOVE
)
859 if ( geom
== wxLIST_NEXT_ALL
)
861 if ( geom
== wxLIST_NEXT_BELOW
)
863 if ( geom
== wxLIST_NEXT_LEFT
)
864 flags
|= LVNI_TOLEFT
;
865 if ( geom
== wxLIST_NEXT_RIGHT
)
866 flags
|= LVNI_TORIGHT
;
868 if ( state
& wxLIST_STATE_CUT
)
870 if ( state
& wxLIST_STATE_DROPHILITED
)
871 flags
|= LVNI_DROPHILITED
;
872 if ( state
& wxLIST_STATE_FOCUSED
)
873 flags
|= LVNI_FOCUSED
;
874 if ( state
& wxLIST_STATE_SELECTED
)
875 flags
|= LVNI_SELECTED
;
877 return (long) ListView_GetNextItem(GetHwnd(), item
, flags
);
881 wxImageList
*wxListCtrl::GetImageList(int which
) const
883 if ( which
== wxIMAGE_LIST_NORMAL
)
885 return m_imageListNormal
;
887 else if ( which
== wxIMAGE_LIST_SMALL
)
889 return m_imageListSmall
;
891 else if ( which
== wxIMAGE_LIST_STATE
)
893 return m_imageListState
;
898 void wxListCtrl::SetImageList(wxImageList
*imageList
, int which
)
901 if ( which
== wxIMAGE_LIST_NORMAL
)
903 flags
= LVSIL_NORMAL
;
904 m_imageListNormal
= imageList
;
906 else if ( which
== wxIMAGE_LIST_SMALL
)
909 m_imageListSmall
= imageList
;
911 else if ( which
== wxIMAGE_LIST_STATE
)
914 m_imageListState
= imageList
;
916 ListView_SetImageList(GetHwnd(), (HIMAGELIST
) imageList
? imageList
->GetHIMAGELIST() : 0, flags
);
919 // ----------------------------------------------------------------------------
921 // ----------------------------------------------------------------------------
923 // Arranges the items
924 bool wxListCtrl::Arrange(int flag
)
927 if ( flag
== wxLIST_ALIGN_LEFT
)
928 code
= LVA_ALIGNLEFT
;
929 else if ( flag
== wxLIST_ALIGN_TOP
)
931 else if ( flag
== wxLIST_ALIGN_DEFAULT
)
933 else if ( flag
== wxLIST_ALIGN_SNAP_TO_GRID
)
934 code
= LVA_SNAPTOGRID
;
936 return (ListView_Arrange(GetHwnd(), code
) != 0);
940 bool wxListCtrl::DeleteItem(long item
)
942 return (ListView_DeleteItem(GetHwnd(), (int) item
) != 0);
946 bool wxListCtrl::DeleteAllItems()
948 return (ListView_DeleteAllItems(GetHwnd()) != 0);
952 bool wxListCtrl::DeleteAllColumns()
954 while ( m_colCount
> 0 )
956 if ( ListView_DeleteColumn(GetHwnd(), 0) == 0 )
958 wxLogLastError(wxT("ListView_DeleteColumn"));
966 wxASSERT_MSG( m_colCount
== 0, wxT("no columns should be left") );
972 bool wxListCtrl::DeleteColumn(int col
)
974 bool success
= (ListView_DeleteColumn(GetHwnd(), col
) != 0);
976 if ( success
&& (m_colCount
> 0) )
981 // Clears items, and columns if there are any.
982 void wxListCtrl::ClearAll()
985 if ( m_colCount
> 0 )
989 wxTextCtrl
* wxListCtrl::EditLabel(long item
, wxClassInfo
* textControlClass
)
991 wxASSERT( (textControlClass
->IsKindOf(CLASSINFO(wxTextCtrl
))) );
993 HWND hWnd
= (HWND
) ListView_EditLabel(GetHwnd(), item
);
997 m_textCtrl
->UnsubclassWin();
998 m_textCtrl
->SetHWND(0);
1003 m_textCtrl
= (wxTextCtrl
*) textControlClass
->CreateObject();
1004 m_textCtrl
->SetHWND((WXHWND
) hWnd
);
1005 m_textCtrl
->SubclassWin((WXHWND
) hWnd
);
1010 // End label editing, optionally cancelling the edit
1011 bool wxListCtrl::EndEditLabel(bool cancel
)
1015 /* I don't know how to implement this: there's no such macro as ListView_EndEditLabelNow.
1017 bool success = (ListView_EndEditLabelNow(GetHwnd(), cancel) != 0);
1021 m_textCtrl->UnsubclassWin();
1022 m_textCtrl->SetHWND(0);
1032 // Ensures this item is visible
1033 bool wxListCtrl::EnsureVisible(long item
)
1035 return (ListView_EnsureVisible(GetHwnd(), (int) item
, FALSE
) != 0);
1038 // Find an item whose label matches this string, starting from the item after 'start'
1039 // or the beginning if 'start' is -1.
1040 long wxListCtrl::FindItem(long start
, const wxString
& str
, bool partial
)
1042 LV_FINDINFO findInfo
;
1044 findInfo
.flags
= LVFI_STRING
;
1046 findInfo
.flags
|= LVFI_PARTIAL
;
1049 // ListView_FindItem() excludes the first item from search and to look
1050 // through all the items you need to start from -1 which is unnatural and
1051 // inconsitent with the generic version - so we adjust the index
1052 return ListView_FindItem(GetHwnd(), (int) start
- 1, &findInfo
);
1055 // Find an item whose data matches this data, starting from the item after 'start'
1056 // or the beginning if 'start' is -1.
1057 long wxListCtrl::FindItem(long start
, long data
)
1059 LV_FINDINFO findInfo
;
1061 findInfo
.flags
= LVFI_PARAM
;
1062 findInfo
.lParam
= data
;
1064 return ListView_FindItem(GetHwnd(), (int) start
, & findInfo
);
1067 // Find an item nearest this position in the specified direction, starting from
1068 // the item after 'start' or the beginning if 'start' is -1.
1069 long wxListCtrl::FindItem(long start
, const wxPoint
& pt
, int direction
)
1071 LV_FINDINFO findInfo
;
1073 findInfo
.flags
= LVFI_NEARESTXY
;
1074 findInfo
.pt
.x
= pt
.x
;
1075 findInfo
.pt
.y
= pt
.y
;
1076 findInfo
.vkDirection
= VK_RIGHT
;
1078 if ( direction
== wxLIST_FIND_UP
)
1079 findInfo
.vkDirection
= VK_UP
;
1080 else if ( direction
== wxLIST_FIND_DOWN
)
1081 findInfo
.vkDirection
= VK_DOWN
;
1082 else if ( direction
== wxLIST_FIND_LEFT
)
1083 findInfo
.vkDirection
= VK_LEFT
;
1084 else if ( direction
== wxLIST_FIND_RIGHT
)
1085 findInfo
.vkDirection
= VK_RIGHT
;
1087 return ListView_FindItem(GetHwnd(), (int) start
, & findInfo
);
1090 // Determines which item (if any) is at the specified point,
1091 // giving details in 'flags' (see wxLIST_HITTEST_... flags above)
1092 long wxListCtrl::HitTest(const wxPoint
& point
, int& flags
)
1094 LV_HITTESTINFO hitTestInfo
;
1095 hitTestInfo
.pt
.x
= (int) point
.x
;
1096 hitTestInfo
.pt
.y
= (int) point
.y
;
1098 ListView_HitTest(GetHwnd(), & hitTestInfo
);
1101 if ( hitTestInfo
.flags
& LVHT_ABOVE
)
1102 flags
|= wxLIST_HITTEST_ABOVE
;
1103 if ( hitTestInfo
.flags
& LVHT_BELOW
)
1104 flags
|= wxLIST_HITTEST_BELOW
;
1105 if ( hitTestInfo
.flags
& LVHT_NOWHERE
)
1106 flags
|= wxLIST_HITTEST_NOWHERE
;
1107 if ( hitTestInfo
.flags
& LVHT_ONITEMICON
)
1108 flags
|= wxLIST_HITTEST_ONITEMICON
;
1109 if ( hitTestInfo
.flags
& LVHT_ONITEMLABEL
)
1110 flags
|= wxLIST_HITTEST_ONITEMLABEL
;
1111 if ( hitTestInfo
.flags
& LVHT_ONITEMSTATEICON
)
1112 flags
|= wxLIST_HITTEST_ONITEMSTATEICON
;
1113 if ( hitTestInfo
.flags
& LVHT_TOLEFT
)
1114 flags
|= wxLIST_HITTEST_TOLEFT
;
1115 if ( hitTestInfo
.flags
& LVHT_TORIGHT
)
1116 flags
|= wxLIST_HITTEST_TORIGHT
;
1118 return (long) hitTestInfo
.iItem
;
1121 // Inserts an item, returning the index of the new item if successful,
1123 long wxListCtrl::InsertItem(wxListItem
& info
)
1126 wxConvertToMSWListItem(this, info
, item
);
1128 // check whether it has any custom attributes
1129 if ( info
.HasAttributes() )
1131 wxListItemAttr
*attr
;
1132 attr
= (wxListItemAttr
*) m_attrs
.Get(item
.iItem
);
1134 m_attrs
.Put(item
.iItem
, (wxObject
*)new wxListItemAttr(*info
.GetAttributes()));
1135 else *attr
= *info
.GetAttributes();
1137 m_hasAnyAttr
= TRUE
;
1140 return (long) ListView_InsertItem(GetHwnd(), & item
);
1143 long wxListCtrl::InsertItem(long index
, const wxString
& label
)
1146 info
.m_text
= label
;
1147 info
.m_mask
= wxLIST_MASK_TEXT
;
1148 info
.m_itemId
= index
;
1149 return InsertItem(info
);
1152 // Inserts an image item
1153 long wxListCtrl::InsertItem(long index
, int imageIndex
)
1156 info
.m_image
= imageIndex
;
1157 info
.m_mask
= wxLIST_MASK_IMAGE
;
1158 info
.m_itemId
= index
;
1159 return InsertItem(info
);
1162 // Inserts an image/string item
1163 long wxListCtrl::InsertItem(long index
, const wxString
& label
, int imageIndex
)
1166 info
.m_image
= imageIndex
;
1167 info
.m_text
= label
;
1168 info
.m_mask
= wxLIST_MASK_IMAGE
| wxLIST_MASK_TEXT
;
1169 info
.m_itemId
= index
;
1170 return InsertItem(info
);
1173 // For list view mode (only), inserts a column.
1174 long wxListCtrl::InsertColumn(long col
, wxListItem
& item
)
1179 lvCol
.pszText
= NULL
;
1181 if ( item
.m_mask
& wxLIST_MASK_TEXT
)
1183 lvCol
.mask
|= LVCF_TEXT
;
1184 lvCol
.pszText
= WXSTRINGCAST item
.m_text
;
1185 lvCol
.cchTextMax
= 0; // Ignored
1187 if ( item
.m_mask
& wxLIST_MASK_FORMAT
)
1189 lvCol
.mask
|= LVCF_FMT
;
1191 if ( item
.m_format
== wxLIST_FORMAT_LEFT
)
1192 lvCol
.fmt
= LVCFMT_LEFT
;
1193 if ( item
.m_format
== wxLIST_FORMAT_RIGHT
)
1194 lvCol
.fmt
= LVCFMT_RIGHT
;
1195 if ( item
.m_format
== wxLIST_FORMAT_CENTRE
)
1196 lvCol
.fmt
= LVCFMT_CENTER
;
1199 lvCol
.mask
|= LVCF_WIDTH
;
1200 if ( item
.m_mask
& wxLIST_MASK_WIDTH
)
1202 if ( item
.m_width
== wxLIST_AUTOSIZE
)
1203 lvCol
.cx
= LVSCW_AUTOSIZE
;
1204 else if ( item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
1205 lvCol
.cx
= LVSCW_AUTOSIZE_USEHEADER
;
1207 lvCol
.cx
= item
.m_width
;
1211 // always give some width to the new column: this one is compatible
1216 lvCol
.mask
|= LVCF_SUBITEM
;
1217 lvCol
.iSubItem
= col
;
1219 bool success
= ListView_InsertColumn(GetHwnd(), col
, & lvCol
) != -1;
1226 wxLogDebug(wxT("Failed to insert the column '%s' into listview!"),
1233 long wxListCtrl::InsertColumn(long col
,
1234 const wxString
& heading
,
1239 item
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_FORMAT
;
1240 item
.m_text
= heading
;
1243 item
.m_mask
|= wxLIST_MASK_WIDTH
;
1244 item
.m_width
= width
;
1246 item
.m_format
= format
;
1248 return InsertColumn(col
, item
);
1251 // Scrolls the list control. If in icon, small icon or report view mode,
1252 // x specifies the number of pixels to scroll. If in list view mode, x
1253 // specifies the number of columns to scroll.
1254 // If in icon, small icon or list view mode, y specifies the number of pixels
1255 // to scroll. If in report view mode, y specifies the number of lines to scroll.
1256 bool wxListCtrl::ScrollList(int dx
, int dy
)
1258 return (ListView_Scroll(GetHwnd(), dx
, dy
) != 0);
1263 // fn is a function which takes 3 long arguments: item1, item2, data.
1264 // item1 is the long data associated with a first item (NOT the index).
1265 // item2 is the long data associated with a second item (NOT the index).
1266 // data is the same value as passed to SortItems.
1267 // The return value is a negative number if the first item should precede the second
1268 // item, a positive number of the second item should precede the first,
1269 // or zero if the two items are equivalent.
1271 // data is arbitrary data to be passed to the sort function.
1272 bool wxListCtrl::SortItems(wxListCtrlCompare fn
, long data
)
1274 return (ListView_SortItems(GetHwnd(), (PFNLVCOMPARE
) fn
, data
) != 0);
1277 // ----------------------------------------------------------------------------
1278 // message processing
1279 // ----------------------------------------------------------------------------
1281 bool wxListCtrl::MSWCommand(WXUINT cmd
, WXWORD id
)
1283 if (cmd
== EN_UPDATE
)
1285 wxCommandEvent
event(wxEVT_COMMAND_TEXT_UPDATED
, id
);
1286 event
.SetEventObject( this );
1287 ProcessCommand(event
);
1290 else if (cmd
== EN_KILLFOCUS
)
1292 wxCommandEvent
event(wxEVT_KILL_FOCUS
, id
);
1293 event
.SetEventObject( this );
1294 ProcessCommand(event
);
1301 bool wxListCtrl::MSWOnNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
1303 // prepare the event
1304 // -----------------
1306 wxListEvent
event(wxEVT_NULL
, m_windowId
);
1307 wxEventType eventType
= wxEVT_NULL
;
1309 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
1311 // almost all messages use NM_LISTVIEW
1312 NM_LISTVIEW
*nmLV
= (NM_LISTVIEW
*)nmhdr
;
1314 // this is true for almost all events
1315 event
.m_item
.m_data
= nmLV
->lParam
;
1317 switch ( nmhdr
->code
)
1319 case LVN_BEGINRDRAG
:
1320 eventType
= wxEVT_COMMAND_LIST_BEGIN_RDRAG
;
1324 if ( eventType
== wxEVT_NULL
)
1326 eventType
= wxEVT_COMMAND_LIST_BEGIN_DRAG
;
1329 event
.m_itemIndex
= nmLV
->iItem
;
1330 event
.m_pointDrag
.x
= nmLV
->ptAction
.x
;
1331 event
.m_pointDrag
.y
= nmLV
->ptAction
.y
;
1334 case LVN_BEGINLABELEDIT
:
1336 eventType
= wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
;
1337 LV_DISPINFO
*info
= (LV_DISPINFO
*)lParam
;
1338 wxConvertFromMSWListItem(this, event
.m_item
, info
->item
, GetHwnd());
1342 case LVN_COLUMNCLICK
:
1343 eventType
= wxEVT_COMMAND_LIST_COL_CLICK
;
1344 event
.m_itemIndex
= -1;
1345 event
.m_col
= nmLV
->iSubItem
;
1348 case LVN_DELETEALLITEMS
:
1349 eventType
= wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
;
1350 event
.m_itemIndex
= -1;
1356 case LVN_DELETEITEM
:
1357 eventType
= wxEVT_COMMAND_LIST_DELETE_ITEM
;
1358 event
.m_itemIndex
= nmLV
->iItem
;
1362 delete (wxListItemAttr
*)m_attrs
.Delete(nmLV
->iItem
);
1366 case LVN_ENDLABELEDIT
:
1368 eventType
= wxEVT_COMMAND_LIST_END_LABEL_EDIT
;
1369 LV_DISPINFO
*info
= (LV_DISPINFO
*)lParam
;
1370 wxConvertFromMSWListItem(this, event
.m_item
, info
->item
);
1371 if ( info
->item
.pszText
== NULL
|| info
->item
.iItem
== -1 )
1376 case LVN_SETDISPINFO
:
1378 eventType
= wxEVT_COMMAND_LIST_SET_INFO
;
1379 LV_DISPINFO
*info
= (LV_DISPINFO
*)lParam
;
1380 wxConvertFromMSWListItem(this, event
.m_item
, info
->item
, GetHwnd());
1384 case LVN_GETDISPINFO
:
1385 // this provokes stack overflow: indeed, wxConvertFromMSWListItem()
1386 // sends us WM_NOTIFY! As it doesn't do anything for now, just leave
1390 // TODO: some text buffering here, I think
1391 // TODO: API for getting Windows to retrieve values
1393 eventType
= wxEVT_COMMAND_LIST_GET_INFO
;
1394 LV_DISPINFO
*info
= (LV_DISPINFO
*)lParam
;
1395 wxConvertFromMSWListItem(this, event
.m_item
, info
->item
, GetHwnd());
1402 case LVN_INSERTITEM
:
1403 eventType
= wxEVT_COMMAND_LIST_INSERT_ITEM
;
1404 event
.m_itemIndex
= nmLV
->iItem
;
1407 case LVN_ITEMCHANGED
:
1408 // This needs to be sent to wxListCtrl as a rather more concrete
1409 // event. For now, just detect a selection or deselection.
1410 if ( (nmLV
->uNewState
& LVIS_SELECTED
) && !(nmLV
->uOldState
& LVIS_SELECTED
) )
1412 eventType
= wxEVT_COMMAND_LIST_ITEM_SELECTED
;
1413 event
.m_itemIndex
= nmLV
->iItem
;
1415 else if ( !(nmLV
->uNewState
& LVIS_SELECTED
) && (nmLV
->uOldState
& LVIS_SELECTED
) )
1417 eventType
= wxEVT_COMMAND_LIST_ITEM_DESELECTED
;
1418 event
.m_itemIndex
= nmLV
->iItem
;
1428 LV_KEYDOWN
*info
= (LV_KEYDOWN
*)lParam
;
1429 WORD wVKey
= info
->wVKey
;
1431 // get the current selection
1432 long lItem
= GetNextItem(-1,
1434 wxLIST_STATE_SELECTED
);
1436 // <Enter> or <Space> activate the selected item if any
1437 if ( lItem
!= -1 && (wVKey
== VK_RETURN
|| wVKey
== VK_SPACE
) )
1439 // TODO this behaviour probably should be optional
1440 eventType
= wxEVT_COMMAND_LIST_ITEM_ACTIVATED
;
1441 event
.m_itemIndex
= lItem
;
1445 eventType
= wxEVT_COMMAND_LIST_KEY_DOWN
;
1446 event
.m_code
= wxCharCodeMSWToWX(wVKey
);
1451 // fill the other fields too
1452 event
.m_item
.m_text
= GetItemText(lItem
);
1453 event
.m_item
.m_data
= GetItemData(lItem
);
1459 // if the user processes it in wxEVT_COMMAND_LEFT_CLICK(), don't do
1461 if ( wxControl::MSWOnNotify(idCtrl
, lParam
, result
) )
1466 // else translate it into wxEVT_COMMAND_LIST_ITEM_ACTIVATED event
1467 // if it happened on an item (and not on empty place)
1468 if ( nmLV
->iItem
== -1 )
1474 eventType
= wxEVT_COMMAND_LIST_ITEM_ACTIVATED
;
1475 event
.m_itemIndex
= nmLV
->iItem
;
1476 event
.m_item
.m_text
= GetItemText(nmLV
->iItem
);
1477 event
.m_item
.m_data
= GetItemData(nmLV
->iItem
);
1481 /* TECH NOTE: NM_RCLICK isn't really good enough here. We want to
1482 subclass and check for the actual WM_RBUTTONDOWN message,
1483 because NM_RCLICK waits for the WM_RBUTTONUP message as well
1484 before firing off. We want to have notify events for both down
1487 // if the user processes it in wxEVT_COMMAND_RIGHT_CLICK(),
1488 // don't do anything else
1489 if ( wxControl::MSWOnNotify(idCtrl
, lParam
, result
) )
1494 // else translate it into wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK event
1495 LV_HITTESTINFO lvhti
;
1496 wxZeroMemory(lvhti
);
1498 ::GetCursorPos(&(lvhti
.pt
));
1499 ::ScreenToClient(GetHwnd(),&(lvhti
.pt
));
1500 if ( ListView_HitTest(GetHwnd(),&lvhti
) != -1 )
1502 if ( lvhti
.flags
& LVHT_ONITEM
)
1504 eventType
= wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
;
1505 event
.m_itemIndex
= lvhti
.iItem
;
1512 case NM_MCLICK
: // ***** THERE IS NO NM_MCLICK. Subclass anyone? ******
1514 // if the user processes it in wxEVT_COMMAND_MIDDLE_CLICK(), don't do
1516 if ( wxControl::MSWOnNotify(idCtrl
, lParam
, result
) )
1521 // else translate it into wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK event
1522 eventType
= wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
;
1523 NMITEMACTIVATE
* hdr
= (NMITEMACTIVATE
*)lParam
;
1524 event
.m_itemIndex
= hdr
->iItem
;
1529 #if defined(_WIN32_IE) && _WIN32_IE >= 0x300
1532 LPNMLVCUSTOMDRAW lplvcd
= (LPNMLVCUSTOMDRAW
)lParam
;
1533 NMCUSTOMDRAW
& nmcd
= lplvcd
->nmcd
;
1534 switch( nmcd
.dwDrawStage
)
1537 // if we've got any items with non standard attributes,
1538 // notify us before painting each item
1539 *result
= m_hasAnyAttr
? CDRF_NOTIFYITEMDRAW
1543 case CDDS_ITEMPREPAINT
:
1545 wxListItemAttr
*attr
=
1546 (wxListItemAttr
*)m_attrs
.Get(nmcd
.dwItemSpec
);
1550 // nothing to do for this item
1551 return CDRF_DODEFAULT
;
1555 wxColour colText
, colBack
;
1556 if ( attr
->HasFont() )
1558 wxFont font
= attr
->GetFont();
1559 hFont
= (HFONT
)font
.GetResourceHandle();
1566 if ( attr
->HasTextColour() )
1568 colText
= attr
->GetTextColour();
1572 colText
= GetTextColour();
1575 if ( attr
->HasBackgroundColour() )
1577 colBack
= attr
->GetBackgroundColour();
1581 colBack
= GetBackgroundColour();
1584 // note that if we wanted to set colours for
1585 // individual columns (subitems), we would have
1586 // returned CDRF_NOTIFYSUBITEMREDRAW from here
1589 ::SelectObject(nmcd
.hdc
, hFont
);
1591 *result
= CDRF_NEWFONT
;
1595 *result
= CDRF_DODEFAULT
;
1598 lplvcd
->clrText
= wxColourToRGB(colText
);
1599 lplvcd
->clrTextBk
= wxColourToRGB(colBack
);
1605 *result
= CDRF_DODEFAULT
;
1610 #endif // _WIN32_IE >= 0x300
1613 return wxControl::MSWOnNotify(idCtrl
, lParam
, result
);
1616 // process the event
1617 // -----------------
1619 event
.SetEventObject( this );
1620 event
.SetEventType(eventType
);
1622 if ( !GetEventHandler()->ProcessEvent(event
) )
1628 switch ( nmhdr
->code
)
1630 case LVN_DELETEALLITEMS
:
1631 // always return TRUE to suppress all additional LVN_DELETEITEM
1632 // notifications - this makes deleting all items from a list ctrl
1638 case LVN_GETDISPINFO
:
1640 LV_DISPINFO
*info
= (LV_DISPINFO
*)lParam
;
1641 if ( info
->item
.mask
& LVIF_TEXT
)
1643 if ( !event
.m_item
.m_text
.IsNull() )
1645 info
->item
.pszText
= AddPool(event
.m_item
.m_text
);
1646 info
->item
.cchTextMax
= wxStrlen(info
->item
.pszText
) + 1;
1649 // wxConvertToMSWListItem(this, event.m_item, info->item);
1652 case LVN_ENDLABELEDIT
:
1654 *result
= event
.IsAllowed();
1659 *result
= !event
.IsAllowed();
1664 wxChar
*wxListCtrl::AddPool(const wxString
& str
)
1666 // Remove the first element if 3 strings exist
1667 if ( m_stringPool
.Number() == 3 )
1669 wxNode
*node
= m_stringPool
.First();
1670 delete[] (char *)node
->Data();
1673 wxNode
*node
= m_stringPool
.Add(WXSTRINGCAST str
);
1674 return (wxChar
*)node
->Data();
1677 // ----------------------------------------------------------------------------
1679 // ----------------------------------------------------------------------------
1681 // List item structure
1682 wxListItem::wxListItem()
1692 m_format
= wxLIST_FORMAT_CENTRE
;
1698 void wxListItem::Clear()
1707 m_format
= wxLIST_FORMAT_CENTRE
;
1709 m_text
= wxEmptyString
;
1711 if (m_attr
) delete m_attr
;
1715 void wxListItem::ClearAttributes()
1717 if (m_attr
) delete m_attr
;
1721 static void wxConvertFromMSWListItem(const wxListCtrl
*ctrl
, wxListItem
& info
, LV_ITEM
& lvItem
, HWND getFullInfo
)
1723 info
.m_data
= lvItem
.lParam
;
1726 info
.m_stateMask
= 0;
1727 info
.m_itemId
= lvItem
.iItem
;
1729 long oldMask
= lvItem
.mask
;
1731 bool needText
= FALSE
;
1732 if (getFullInfo
!= 0)
1734 if ( lvItem
.mask
& LVIF_TEXT
)
1741 lvItem
.pszText
= new wxChar
[513];
1742 lvItem
.cchTextMax
= 512;
1744 // lvItem.mask |= TVIF_HANDLE | TVIF_STATE | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
1745 lvItem
.mask
|= LVIF_TEXT
| LVIF_IMAGE
| LVIF_PARAM
;
1746 ::SendMessage(getFullInfo
, LVM_GETITEM
, 0, (LPARAM
)& lvItem
);
1749 if ( lvItem
.mask
& LVIF_STATE
)
1751 info
.m_mask
|= wxLIST_MASK_STATE
;
1753 if ( lvItem
.stateMask
& LVIS_CUT
)
1755 info
.m_stateMask
|= wxLIST_STATE_CUT
;
1756 if ( lvItem
.state
& LVIS_CUT
)
1757 info
.m_state
|= wxLIST_STATE_CUT
;
1759 if ( lvItem
.stateMask
& LVIS_DROPHILITED
)
1761 info
.m_stateMask
|= wxLIST_STATE_DROPHILITED
;
1762 if ( lvItem
.state
& LVIS_DROPHILITED
)
1763 info
.m_state
|= wxLIST_STATE_DROPHILITED
;
1765 if ( lvItem
.stateMask
& LVIS_FOCUSED
)
1767 info
.m_stateMask
|= wxLIST_STATE_FOCUSED
;
1768 if ( lvItem
.state
& LVIS_FOCUSED
)
1769 info
.m_state
|= wxLIST_STATE_FOCUSED
;
1771 if ( lvItem
.stateMask
& LVIS_SELECTED
)
1773 info
.m_stateMask
|= wxLIST_STATE_SELECTED
;
1774 if ( lvItem
.state
& LVIS_SELECTED
)
1775 info
.m_state
|= wxLIST_STATE_SELECTED
;
1779 if ( lvItem
.mask
& LVIF_TEXT
)
1781 info
.m_mask
|= wxLIST_MASK_TEXT
;
1782 info
.m_text
= lvItem
.pszText
;
1784 if ( lvItem
.mask
& LVIF_IMAGE
)
1786 info
.m_mask
|= wxLIST_MASK_IMAGE
;
1787 info
.m_image
= lvItem
.iImage
;
1789 if ( lvItem
.mask
& LVIF_PARAM
)
1790 info
.m_mask
|= wxLIST_MASK_DATA
;
1791 if ( lvItem
.mask
& LVIF_DI_SETITEM
)
1792 info
.m_mask
|= wxLIST_SET_ITEM
;
1793 info
.m_col
= lvItem
.iSubItem
;
1798 delete[] lvItem
.pszText
;
1800 lvItem
.mask
= oldMask
;
1803 static void wxConvertToMSWListItem(const wxListCtrl
*ctrl
, wxListItem
& info
, LV_ITEM
& lvItem
)
1805 lvItem
.iItem
= (int) info
.m_itemId
;
1807 lvItem
.iImage
= info
.m_image
;
1808 lvItem
.lParam
= info
.m_data
;
1809 lvItem
.stateMask
= 0;
1812 lvItem
.iSubItem
= info
.m_col
;
1814 if (info
.m_mask
& wxLIST_MASK_STATE
)
1816 lvItem
.mask
|= LVIF_STATE
;
1817 if (info
.m_stateMask
& wxLIST_STATE_CUT
)
1819 lvItem
.stateMask
|= LVIS_CUT
;
1820 if (info
.m_state
& wxLIST_STATE_CUT
)
1821 lvItem
.state
|= LVIS_CUT
;
1823 if (info
.m_stateMask
& wxLIST_STATE_DROPHILITED
)
1825 lvItem
.stateMask
|= LVIS_DROPHILITED
;
1826 if (info
.m_state
& wxLIST_STATE_DROPHILITED
)
1827 lvItem
.state
|= LVIS_DROPHILITED
;
1829 if (info
.m_stateMask
& wxLIST_STATE_FOCUSED
)
1831 lvItem
.stateMask
|= LVIS_FOCUSED
;
1832 if (info
.m_state
& wxLIST_STATE_FOCUSED
)
1833 lvItem
.state
|= LVIS_FOCUSED
;
1835 if (info
.m_stateMask
& wxLIST_STATE_SELECTED
)
1837 lvItem
.stateMask
|= LVIS_SELECTED
;
1838 if (info
.m_state
& wxLIST_STATE_SELECTED
)
1839 lvItem
.state
|= LVIS_SELECTED
;
1843 if (info
.m_mask
& wxLIST_MASK_TEXT
)
1845 lvItem
.mask
|= LVIF_TEXT
;
1846 if ( ctrl
->GetWindowStyleFlag() & wxLC_USER_TEXT
)
1848 lvItem
.pszText
= LPSTR_TEXTCALLBACK
;
1852 lvItem
.pszText
= WXSTRINGCAST info
.m_text
;
1853 if ( lvItem
.pszText
)
1854 lvItem
.cchTextMax
= info
.m_text
.Length();
1856 lvItem
.cchTextMax
= 0;
1859 if (info
.m_mask
& wxLIST_MASK_IMAGE
)
1860 lvItem
.mask
|= LVIF_IMAGE
;
1861 if (info
.m_mask
& wxLIST_MASK_DATA
)
1862 lvItem
.mask
|= LVIF_PARAM
;
1865 // ----------------------------------------------------------------------------
1867 // ----------------------------------------------------------------------------
1869 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
)
1871 wxListEvent::wxListEvent(wxEventType commandType
, int id
)
1872 : wxNotifyEvent(commandType
, id
)
1878 m_cancelled
= FALSE
;