WxListCtrl

From WxWiki

Jump to: navigation, search

If wxListCtrl has more features than you need, have a look at wxListView. For a simpler listing control, look at wxListBox.

Contents

[edit] Adding Images

m_pImageList = new wxImageList(16,16);
wxIcon icon;
icon.LoadFile(wxT("res/user_offline.ico"), wxBITMAP_TYPE_ICO);
m_pImageList->Add(icon);
SetImageList(m_pImageList, wxIMAGE_LIST_SMALL);

And when you add an item, after that call

SetItemImage(item, 0);

[edit] Deleting Selected Rows

Rows (or items) in a listctrl are indexed starting from zero. You often want to delete some items that the user has selected. Get the index numbers of the selected items, and then looping through, delete the selected items. Warning If you delete items starting at the lowest index, the higher index numbers will now point to different items than they did before the deletion. Subsequent deletions will erase the wrong items. Rather loop through starting with the highest index first. For example:

// Make a list of selected row numbers that you want to delete by 
// whatever means your application decides when ones should be deleted.
wxArrayInt row_numbers_to_delete = ......
 
// Delete in reverse order.
if ( ! row_numbers_to_delete.IsEmpty() ) 
   {
      for ( long n = ( row_numbers_to_delete.GetCount() -1 ); 0 <= n; n-- )
      {
         // Remove it from the listctrl.
         DeleteItem( row_numbers_to_delete[ n ] );
      }
   }
 
// Usual clearing of arrays to free memory.
row_numbers_to_delete.Clear();

[edit] Get the String Contents of a "cell" in a LC_REPORT wxListCtrl

The functionality to extract a string from a wxListCtrl "cell" in report view is somewhat rough for a newcomer to wxWidgets who is looking through the API. By "cell", we mean the value located at a certain "row" under a certain "column". This code snippet will return the string at that numbered row and column. Each row and column starts at index number zero. Place this custom function in your derived wxListCtrl.

wxString MyListCtrl::GetCellContentsString( long row_number, int column ) 
{
   wxListItem     row_info;  
   wxString       cell_contents_string;
 
   // Set what row it is (m_itemId is a member of the regular wxListCtrl class)
   row_info.m_itemId = row_number;
   // Set what column of that row we want to query for information.
   row_info.m_col = column;
   // Set text mask
   row_info.m_mask = wxLIST_MASK_TEXT;
 
   // Get the info and store it in row_info variable.   
   GetItem( row_info );
 
   // Extract the text out that cell
   cell_contents_string = row_info.m_text; 
 
   return cell_contents_string;
}

An alternative definition:

bool MyListCtrl::GetCellContentsString( long row_number, int column, wxString& cell_contents_string ) const
{
   wxListItem row_info;
 
   // Set what row it is (m_itemId is a member of the regular wxListCtrl class)
   row_info.m_itemId = row_number;
   // Set what column of that row we want to query for information.
   row_info.m_col = column;
   // Set text mask
   row_info.m_mask = wxLIST_MASK_TEXT;
 
   // Get the info and store it in row_info variable.
   if (GetItem( row_info ))
   {
       // Extract the text out of that cell
       cell_contents_string = row_info.m_text;
       return true;
   }
 
   return false;
}

[edit] Select or Deselect an Item

More constraints - see help: wxListCtrl::SetItem

// Deselect item (wxLIST_STATE_FOCUSED - dotted border)
wxListCtrl->SetItemState(item, 0, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
 
// Select item
wxListCtrl->SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);

Note that the second parameter, stateMask in wxListCtrl::SetItemState is not the same as the mask used in wxListItem (although the actual flags are the same). The stateMask simply specifies which flags in state are valid. As the above example shows, to select an item, both the state and stateMask must be set to wxLIST_STATE_SELECTED.

[edit] Implement wxListCtrl with Checkboxes

This is quite easy using checked and unchecked images. If you want a more complete version of wxCheckedListCtrl with events for checking and unchecking and completely transparent wxWidgets behaviour, see WebUpdate at wxCode. It contains a wxCheckedListCtrl implementation which can be extracted and used separately from WebUpdate. Just move the header and source file, checkedlistctrl.cpp/.h into your project.

wxCheckedListCtrl
#include <bitmaps/checked.xpm>
#include <bitmaps/unchecked.xpm>
 
IMPLEMENT_CLASS(wxCheckedListCtrl, wxListCtrl)
 
BEGIN_EVENT_TABLE(wxCheckedListCtrl, wxListCtrl)
  EVT_LEFT_DOWN(wxCheckedListCtrl::OnMouseEvent)
END_EVENT_TABLE()
 
wxCheckedListCtrl::wxCheckedListCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pt,
   const wxSize& sz, long style):
   wxListCtrl(parent, id, pt, sz, style), m_imageList(16, 16, TRUE)
   {
   SetImageList(&m_imageList, wxIMAGE_LIST_SMALL);
 
   m_imageList.Add(wxICON(unchecked));
   m_imageList.Add(wxICON(checked));
 
   InsertColumn(0, _("Item"), wxLIST_FORMAT_LEFT, 200);
   InsertColumn(1, _("Value"), wxLIST_FORMAT_LEFT, 80);
   }
 
   void wxCheckedListCtrl::OnMouseEvent(wxMouseEvent& event)
   {
      if (event.LeftDown())
      {
         int flags;
         long item = HitTest(event.GetPosition(), flags);
         if (item > -1 && (flags & wxLIST_HITTEST_ONITEMICON))
         {
             SetChecked(item, !IsChecked(item));
         }
         else
            event.Skip();
      }
      else
      {
         event.Skip();
      }
   }
 
bool wxCheckedListCtrl::IsChecked(long item) const
{
   wxListItem info;
   info.m_mask = wxLIST_MASK_IMAGE ;
   info.m_itemId = item;
 
   if (GetItem(info))
   {
      return (info.m_image == 1);
   }
   else
      return FALSE;
}
 
void wxCheckedListCtrl::SetChecked(long item, bool checked)
{
   SetItemImage(item, (checked ? 1 : 0), -1);
}

[edit] Using Specific Colours for Each Item

Trying to set specific item colours for a wxListCtrl doesn't have any effect with wxMSW 2.4.0 standard release. You have to enable it. Indeed, it is not set as default in the downloadable releases so you will have to recompile the library with _WIN32_IE at least defined as 0x300. To do so, just insert the -D_WIN32_IE=0x300 compile flag when making. See the Compiling_WxWidgets for further details. Then, just use wxListItem's methods to set the text colour, background colour and font of each item. For example:

MyListCtrl::AppendColouredItem(const wxString& Label) {
   wxListItem NewItem;
 
   NewItem.SetMask(wxLIST_MASK_TEXT);
   NewItem.SetId(GetItemCount());
   NewItem.SetText(sLabel);
   NewItem.SetFont(*wxITALIC_FONT);
   NewItem.SetTextColour(wxColour(*wxRED));
   NewItem.SetBackgroundColour(wxColour(235, 235, 235));
 
   InsertItem(NewItem);
}

This piece of code appends a new line (item) to MyListCtrl with the label of sLabel's value, an italic font, a red text colour and a light grey background.

NOTE: It seems that these methods still don't work with columns so the tip is to set the global text/background colours and font of MyListCtrl and then, when you append an item, set its colours/font to the proper values.

[edit] wxListCtrl::SetSingleStyle

The wxListCtrl::SetSingleStyle(long style, const bool add = true) function calls SetWindowStyleFlag(long style) which will delete all items. Use it before filling the control with items.

[edit] Official Documentation

wxListCtrl Class Reference

Personal tools