1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/wince/checklst.cpp 
   3 // Purpose:     implementation of wxCheckListBox class 
   4 // Author:      Wlodzimierz ABX Skiba 
   8 // Copyright:   (c) Wlodzimierz Skiba 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  27 #if wxUSE_CHECKLISTBOX 
  29 #include "wx/checklst.h" 
  32     #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly" 
  35 // ============================================================================ 
  37 // ============================================================================ 
  39 IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox
, wxControl
) 
  41 // ---------------------------------------------------------------------------- 
  42 // implementation of wxCheckListBox class 
  43 // ---------------------------------------------------------------------------- 
  47 BEGIN_EVENT_TABLE(wxCheckListBox
, wxControl
) 
  48     EVT_SIZE(wxCheckListBox::OnSize
) 
  54 // def ctor: use Create() to really create the control 
  55 wxCheckListBox::wxCheckListBox() 
  59 // ctor which creates the associated control 
  60 wxCheckListBox::wxCheckListBox(wxWindow 
*parent
, wxWindowID id
, 
  61                                const wxPoint
& pos
, const wxSize
& size
, 
  62                                int nStrings
, const wxString choices
[], 
  63                                long style
, const wxValidator
& val
, 
  66     Create(parent
, id
, pos
, size
, nStrings
, choices
, style
, val
, name
); 
  69 wxCheckListBox::wxCheckListBox(wxWindow 
*parent
, wxWindowID id
, 
  70                                const wxPoint
& pos
, const wxSize
& size
, 
  71                                const wxArrayString
& choices
, 
  72                                long style
, const wxValidator
& val
, 
  75     Create(parent
, id
, pos
, size
, choices
, style
, val
, name
); 
  78 wxCheckListBox::~wxCheckListBox() 
  80     m_itemsClientData
.Clear(); 
  83 bool wxCheckListBox::Create(wxWindow 
*parent
, wxWindowID id
, 
  84                             const wxPoint
& pos
, const wxSize
& size
, 
  85                             int n
, const wxString choices
[], 
  87                             const wxValidator
& validator
, const wxString
& name
) 
  89     // initialize base class fields 
  90     if ( !CreateControl(parent
, id
, pos
, size
, style
, validator
, name
) ) 
  93     // create the native control 
  94     if ( !MSWCreateControl(WC_LISTVIEW
, wxEmptyString
, pos
, size
) ) 
  96         // control creation failed 
 100     ::SendMessage(GetHwnd(), LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, 
 101                   LVS_EX_CHECKBOXES 
| LVS_EX_FULLROWSELECT 
); 
 103     // insert single column with checkboxes and labels 
 106     ListView_InsertColumn(GetHwnd(), 0, &col 
); 
 108     ListView_SetItemCount( GetHwnd(), n 
); 
 110     // initialize the contents 
 111     for ( int i 
= 0; i 
< n
; i
++ ) 
 116     m_itemsClientData
.SetCount(n
); 
 118     // now we can compute our best size correctly, so do it if necessary 
 119     SetInitialSize(size
); 
 124 bool wxCheckListBox::Create(wxWindow 
*parent
, wxWindowID id
, 
 125                             const wxPoint
& pos
, const wxSize
& size
, 
 126                             const wxArrayString
& choices
, 
 128                             const wxValidator
& validator
, const wxString
& name
) 
 130     wxCArrayString 
chs(choices
); 
 131     return Create(parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(), 
 132                   style
, validator
, name
); 
 135 WXDWORD 
wxCheckListBox::MSWGetStyle(long style
, WXDWORD 
*exstyle
) const 
 137     WXDWORD wstyle 
= wxControl::MSWGetStyle(style
, exstyle
); 
 139     wstyle 
|= LVS_REPORT 
| LVS_NOCOLUMNHEADER 
| LVS_NOSORTHEADER
; 
 144 void wxCheckListBox::OnSize(wxSizeEvent
& event
) 
 146     // set width of the column we use to the width of list client area 
 148     int w 
= GetClientSize().x
; 
 149     ListView_SetColumnWidth( GetHwnd(), 0, w 
); 
 152 // misc overloaded methods 
 153 // ----------------------- 
 155 void wxCheckListBox::Delete(unsigned int n
) 
 157     wxCHECK_RET( IsValid( n 
), _T("invalid index in wxCheckListBox::Delete") ); 
 159     if ( !ListView_DeleteItem(GetHwnd(), n
) ) 
 161         wxLogLastError(_T("ListView_DeleteItem")); 
 163     m_itemsClientData
.RemoveAt(n
); 
 169 bool wxCheckListBox::IsChecked(unsigned int uiIndex
) const 
 171     wxCHECK_MSG( IsValid( uiIndex 
), false, 
 172                  _T("invalid index in wxCheckListBox::IsChecked") ); 
 174     return (ListView_GetCheckState(((HWND
)GetHWND()), uiIndex
) != 0); 
 177 void wxCheckListBox::Check(unsigned int uiIndex
, bool bCheck
) 
 179     wxCHECK_RET( IsValid( uiIndex 
), 
 180                  _T("invalid index in wxCheckListBox::Check") ); 
 182     ListView_SetCheckState(((HWND
)GetHWND()), uiIndex
, bCheck
) 
 185 // interface derived from wxListBox and lower classes 
 186 // -------------------------------------------------- 
 188 void wxCheckListBox::Clear() 
 190     unsigned int n 
= GetCount(); 
 198     m_itemsClientData
.Clear(); 
 200     wxCHECK_RET( n 
== GetCount(), 
 201                  _T("broken wxCheckListBox::Clear()") ); 
 204 unsigned int wxCheckListBox::GetCount() const 
 206     return (unsigned int)ListView_GetItemCount( (HWND
)GetHWND() ); 
 209 int wxCheckListBox::GetSelection() const 
 212     for (i 
= 0; (unsigned int)i 
< GetCount(); i
++) 
 214         int selState 
= ListView_GetItemState(GetHwnd(), i
, LVIS_SELECTED
); 
 215         if (selState 
== LVIS_SELECTED
) 
 222 int wxCheckListBox::GetSelections(wxArrayInt
& aSelections
) const 
 225     for (i 
= 0; (unsigned int)i 
< GetCount(); i
++) 
 227         int selState 
= ListView_GetItemState(GetHwnd(), i
, LVIS_SELECTED
); 
 228         if (selState 
== LVIS_SELECTED
) 
 232     return aSelections
.GetCount(); 
 235 wxString 
wxCheckListBox::GetString(unsigned int n
) const 
 237     const int bufSize 
= 513; 
 239     ListView_GetItemText( (HWND
)GetHWND(), n
, 0, buf
, bufSize 
- 1 ); 
 240     buf
[bufSize
-1] = _T('\0'); 
 245 bool wxCheckListBox::IsSelected(int n
) const 
 247     int selState 
= ListView_GetItemState(GetHwnd(), n
, LVIS_SELECTED
); 
 248     return (selState 
== LVIS_SELECTED
); 
 251 void wxCheckListBox::SetString(unsigned int n
, const wxString
& s
) 
 253     wxCHECK_RET( IsValid( n 
), 
 254                  _T("invalid index in wxCheckListBox::SetString") ); 
 255     wxChar 
*buf 
= new wxChar
[s
.length()+1]; 
 256     wxStrcpy(buf
, s
.c_str()); 
 257     ListView_SetItemText( (HWND
)GetHWND(), n
, 0, buf 
); 
 261 int wxCheckListBox::DoAppend(const wxString
& item
) 
 263     int n 
= (int)GetCount(); 
 265     wxZeroMemory(newItem
); 
 267     int ret 
= ListView_InsertItem( (HWND
)GetHWND(), & newItem 
); 
 268     wxCHECK_MSG( n 
== ret 
, -1, _T("Item not added") ); 
 269     SetString( ret 
, item 
); 
 270     m_itemsClientData
.Insert(NULL
, ret
); 
 274 void* wxCheckListBox::DoGetItemClientData(unsigned int n
) const 
 276     return m_itemsClientData
.Item(n
); 
 279 wxClientData
* wxCheckListBox::DoGetItemClientObject(unsigned int n
) const 
 281     return (wxClientData 
*)DoGetItemClientData(n
); 
 284 void wxCheckListBox::DoInsertItems(const wxArrayString
& items
, unsigned int pos
) 
 286     wxCHECK_RET( IsValidInsert( pos 
), 
 287                  wxT("invalid index in wxListBox::InsertItems") ); 
 289     for( unsigned int i 
= 0; i 
< items
.GetCount(); i
++ ) 
 292         wxZeroMemory(newItem
); 
 293         newItem
.iItem 
= i
+pos
; 
 294         int ret 
= ListView_InsertItem( (HWND
)GetHWND(), & newItem 
); 
 295         wxASSERT_MSG( int(i
+pos
) == ret 
, _T("Item not added") ); 
 296         SetString( ret 
, items
[i
] ); 
 297         m_itemsClientData
.Insert(NULL
, ret
); 
 301 void wxCheckListBox::DoSetFirstItem(int n
) 
 303     int pos 
= ListView_GetTopIndex( (HWND
)GetHWND() ); 
 306     BOOL ret 
= ListView_GetItemPosition( (HWND
)GetHWND(), n
, &ppt 
); 
 307     wxCHECK_RET( ret 
== TRUE
, _T("Broken DoSetFirstItem") ); 
 308     ListView_Scroll( (HWND
)GetHWND(), 0, 0 ); 
 309     ListView_Scroll( (HWND
)GetHWND(), 0, ppt
.y 
); 
 312 void wxCheckListBox::DoSetItemClientData(unsigned int n
, void* clientData
) 
 314     m_itemsClientData
.Item(n
) = clientData
; 
 317 void wxCheckListBox::DoSetItemClientObject(unsigned int n
, wxClientData
* clientData
) 
 319     DoSetItemClientData(n
, clientData
); 
 322 void wxCheckListBox::DoSetItems(const wxArrayString
& items
, void **clientData
) 
 324     ListView_SetItemCount( GetHwnd(), GetCount() + items
.GetCount() ); 
 326     for( unsigned int i 
= 0; i 
< items
.GetCount(); i
++ ) 
 328         int pos 
= Append(items
[i
]); 
 329         if( pos 
>= 0 && clientData 
) 
 330             DoSetItemClientData(pos
, clientData
[i
]); 
 334 void wxCheckListBox::DoSetSelection(int n
, bool select
) 
 336     ListView_SetItemState(GetHwnd(), n
, select 
? LVIS_SELECTED 
: 0, LVIS_SELECTED
); 
 339 bool wxCheckListBox::MSWOnNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
 344     wxCommandEvent 
event(wxEVT_NULL
, m_windowId
); 
 345     event
.SetEventObject(this); 
 347     wxEventType eventType 
= wxEVT_NULL
; 
 349     NMHDR 
*nmhdr 
= (NMHDR 
*)lParam
; 
 351     if ( nmhdr
->hwndFrom 
== GetHwnd() ) 
 353         // almost all messages use NM_LISTVIEW 
 354         NM_LISTVIEW 
*nmLV 
= (NM_LISTVIEW 
*)nmhdr
; 
 356         const int iItem 
= nmLV
->iItem
; 
 358         bool processed 
= true; 
 359         switch ( nmhdr
->code 
) 
 361             case LVN_ITEMCHANGED
: 
 362                 // we translate this catch all message into more interesting 
 363                 // (and more easy to process) wxWidgets events 
 365                 // first of all, we deal with the state change events only and 
 366                 // only for valid items (item == -1 for the virtual list 
 368                 if ( nmLV
->uChanged 
& LVIF_STATE 
&& iItem 
!= -1 ) 
 370                     // temp vars for readability 
 371                     const UINT stOld 
= nmLV
->uOldState
; 
 372                     const UINT stNew 
= nmLV
->uNewState
; 
 374                     // Check image changed 
 375                     if ((stOld 
& LVIS_STATEIMAGEMASK
) != (stNew 
& LVIS_STATEIMAGEMASK
)) 
 377                         event
.SetEventType(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
); 
 378                         event
.SetInt(IsChecked(iItem
)); 
 379                         (void) GetEventHandler()->ProcessEvent(event
); 
 382                     if ( (stNew 
& LVIS_SELECTED
) != (stOld 
& LVIS_SELECTED
) ) 
 384                         eventType 
= wxEVT_COMMAND_LISTBOX_SELECTED
; 
 386                         event
.SetExtraLong( (stNew 
& LVIS_SELECTED
) != 0 ); // is a selection 
 391                 if ( eventType 
== wxEVT_NULL 
) 
 393                     // not an interesting event for us 
 404             return wxControl::MSWOnNotify(idCtrl
, lParam
, result
); 
 408         // where did this one come from? 
 415     event
.SetEventType(eventType
); 
 417     bool processed 
= GetEventHandler()->ProcessEvent(event
);