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" 
  34 // include <commctrl.h> "properly" 
  35 #include "wx/msw/wrapcctl.h" 
  37 // ============================================================================ 
  39 // ============================================================================ 
  41 IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox
, wxControl
) 
  43 // ---------------------------------------------------------------------------- 
  44 // implementation of wxCheckListBox class 
  45 // ---------------------------------------------------------------------------- 
  49 BEGIN_EVENT_TABLE(wxCheckListBox
, wxControl
) 
  50     EVT_SIZE(wxCheckListBox::OnSize
) 
  56 // def ctor: use Create() to really create the control 
  57 wxCheckListBox::wxCheckListBox() 
  61 // ctor which creates the associated control 
  62 wxCheckListBox::wxCheckListBox(wxWindow 
*parent
, wxWindowID id
, 
  63                                const wxPoint
& pos
, const wxSize
& size
, 
  64                                int nStrings
, const wxString choices
[], 
  65                                long style
, const wxValidator
& val
, 
  68     Create(parent
, id
, pos
, size
, nStrings
, choices
, style
, val
, name
); 
  71 wxCheckListBox::wxCheckListBox(wxWindow 
*parent
, wxWindowID id
, 
  72                                const wxPoint
& pos
, const wxSize
& size
, 
  73                                const wxArrayString
& choices
, 
  74                                long style
, const wxValidator
& val
, 
  77     Create(parent
, id
, pos
, size
, choices
, style
, val
, name
); 
  80 wxCheckListBox::~wxCheckListBox() 
  82     m_itemsClientData
.Clear(); 
  85 bool wxCheckListBox::Create(wxWindow 
*parent
, wxWindowID id
, 
  86                             const wxPoint
& pos
, const wxSize
& size
, 
  87                             int n
, const wxString choices
[], 
  89                             const wxValidator
& validator
, const wxString
& name
) 
  91     // initialize base class fields 
  92     if ( !CreateControl(parent
, id
, pos
, size
, style
, validator
, name
) ) 
  95     // create the native control 
  96     if ( !MSWCreateControl(WC_LISTVIEW
, wxEmptyString
, pos
, size
) ) 
  98         // control creation failed 
 102     ::SendMessage(GetHwnd(), LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, 
 103                   LVS_EX_CHECKBOXES 
| LVS_EX_FULLROWSELECT 
); 
 105     // insert single column with checkboxes and labels 
 108     ListView_InsertColumn(GetHwnd(), 0, &col 
); 
 110     ListView_SetItemCount( GetHwnd(), n 
); 
 112     // initialize the contents 
 113     for ( int i 
= 0; i 
< n
; i
++ ) 
 118     m_itemsClientData
.SetCount(n
); 
 120     // now we can compute our best size correctly, so do it if necessary 
 126 bool wxCheckListBox::Create(wxWindow 
*parent
, wxWindowID id
, 
 127                             const wxPoint
& pos
, const wxSize
& size
, 
 128                             const wxArrayString
& choices
, 
 130                             const wxValidator
& validator
, const wxString
& name
) 
 132     wxCArrayString 
chs(choices
); 
 133     return Create(parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(), 
 134                   style
, validator
, name
); 
 137 WXDWORD 
wxCheckListBox::MSWGetStyle(long style
, WXDWORD 
*exstyle
) const 
 139     WXDWORD wstyle 
= wxControl::MSWGetStyle(style
, exstyle
); 
 141     wstyle 
|= LVS_REPORT 
| LVS_NOCOLUMNHEADER 
| LVS_NOSORTHEADER
; 
 146 void wxCheckListBox::OnSize(wxSizeEvent
& event
) 
 148     // set width of the column we use to the width of list client area 
 150     int w 
= GetClientSize().x
; 
 151     ListView_SetColumnWidth( GetHwnd(), 0, w 
); 
 154 // misc overloaded methods 
 155 // ----------------------- 
 157 void wxCheckListBox::Delete(unsigned int n
) 
 159     wxCHECK_RET( IsValid( n 
), _T("invalid index in wxCheckListBox::Delete") ); 
 161     if ( !ListView_DeleteItem(GetHwnd(), n
) ) 
 163         wxLogLastError(_T("ListView_DeleteItem")); 
 165     m_itemsClientData
.RemoveAt(n
); 
 171 bool wxCheckListBox::IsChecked(unsigned int uiIndex
) const 
 173     wxCHECK_MSG( IsValid( uiIndex 
), false, 
 174                  _T("invalid index in wxCheckListBox::IsChecked") ); 
 176     return (ListView_GetCheckState(((HWND
)GetHWND()), uiIndex
) != 0); 
 179 void wxCheckListBox::Check(unsigned int uiIndex
, bool bCheck
) 
 181     wxCHECK_RET( IsValid( uiIndex 
), 
 182                  _T("invalid index in wxCheckListBox::Check") ); 
 184     ListView_SetCheckState(((HWND
)GetHWND()), uiIndex
, bCheck
) 
 187 // interface derived from wxListBox and lower classes 
 188 // -------------------------------------------------- 
 190 void wxCheckListBox::Clear() 
 192     unsigned int n 
= GetCount(); 
 200     m_itemsClientData
.Clear(); 
 202     wxCHECK_RET( n 
== GetCount(), 
 203                  _T("broken wxCheckListBox::Clear()") ); 
 206 unsigned int wxCheckListBox::GetCount() const 
 208     return (unsigned int)ListView_GetItemCount( (HWND
)GetHWND() ); 
 211 int wxCheckListBox::GetSelection() const 
 214     for (i 
= 0; (unsigned int)i 
< GetCount(); i
++) 
 216         int selState 
= ListView_GetItemState(GetHwnd(), i
, LVIS_SELECTED
); 
 217         if (selState 
== LVIS_SELECTED
) 
 224 int wxCheckListBox::GetSelections(wxArrayInt
& aSelections
) const 
 227     for (i 
= 0; (unsigned int)i 
< GetCount(); i
++) 
 229         int selState 
= ListView_GetItemState(GetHwnd(), i
, LVIS_SELECTED
); 
 230         if (selState 
== LVIS_SELECTED
) 
 234     return aSelections
.GetCount(); 
 237 wxString 
wxCheckListBox::GetString(unsigned int n
) const 
 239     const int bufSize 
= 513; 
 241     ListView_GetItemText( (HWND
)GetHWND(), n
, 0, buf
, bufSize 
- 1 ); 
 242     buf
[bufSize
-1] = _T('\0'); 
 247 bool wxCheckListBox::IsSelected(int n
) const 
 249     int selState 
= ListView_GetItemState(GetHwnd(), n
, LVIS_SELECTED
); 
 250     return (selState 
== LVIS_SELECTED
); 
 253 void wxCheckListBox::SetString(unsigned int n
, const wxString
& s
) 
 255     wxCHECK_RET( IsValid( n 
), 
 256                  _T("invalid index in wxCheckListBox::SetString") ); 
 257     wxChar 
*buf 
= new wxChar
[s
.length()+1]; 
 258     wxStrcpy(buf
, s
.c_str()); 
 259     ListView_SetItemText( (HWND
)GetHWND(), n
, 0, buf 
); 
 263 int wxCheckListBox::DoAppend(const wxString
& item
) 
 265     int n 
= (int)GetCount(); 
 267     wxZeroMemory(newItem
); 
 269     int ret 
= ListView_InsertItem( (HWND
)GetHWND(), & newItem 
); 
 270     wxCHECK_MSG( n 
== ret 
, -1, _T("Item not added") ); 
 271     SetString( ret 
, item 
); 
 272     m_itemsClientData
.Insert(NULL
, ret
); 
 276 void* wxCheckListBox::DoGetItemClientData(unsigned int n
) const 
 278     return m_itemsClientData
.Item(n
); 
 281 wxClientData
* wxCheckListBox::DoGetItemClientObject(unsigned int n
) const 
 283     return (wxClientData 
*)DoGetItemClientData(n
); 
 286 void wxCheckListBox::DoInsertItems(const wxArrayString
& items
, unsigned int pos
) 
 288     wxCHECK_RET( IsValidInsert( pos 
), 
 289                  wxT("invalid index in wxListBox::InsertItems") ); 
 291     for( unsigned int i 
= 0; i 
< items
.GetCount(); i
++ ) 
 294         wxZeroMemory(newItem
); 
 295         newItem
.iItem 
= i
+pos
; 
 296         int ret 
= ListView_InsertItem( (HWND
)GetHWND(), & newItem 
); 
 297         wxASSERT_MSG( int(i
+pos
) == ret 
, _T("Item not added") ); 
 298         SetString( ret 
, items
[i
] ); 
 299         m_itemsClientData
.Insert(NULL
, ret
); 
 303 void wxCheckListBox::DoSetFirstItem(int n
) 
 305     int pos 
= ListView_GetTopIndex( (HWND
)GetHWND() ); 
 308     BOOL ret 
= ListView_GetItemPosition( (HWND
)GetHWND(), n
, &ppt 
); 
 309     wxCHECK_RET( ret 
== TRUE
, _T("Broken DoSetFirstItem") ); 
 310     ListView_Scroll( (HWND
)GetHWND(), 0, 0 ); 
 311     ListView_Scroll( (HWND
)GetHWND(), 0, ppt
.y 
); 
 314 void wxCheckListBox::DoSetItemClientData(unsigned int n
, void* clientData
) 
 316     m_itemsClientData
.Item(n
) = clientData
; 
 319 void wxCheckListBox::DoSetItemClientObject(unsigned int n
, wxClientData
* clientData
) 
 321     DoSetItemClientData(n
, clientData
); 
 324 void wxCheckListBox::DoSetItems(const wxArrayString
& items
, void **clientData
) 
 326     ListView_SetItemCount( GetHwnd(), GetCount() + items
.GetCount() ); 
 328     for( unsigned int i 
= 0; i 
< items
.GetCount(); i
++ ) 
 330         int pos 
= Append(items
[i
]); 
 331         if( pos 
>= 0 && clientData 
) 
 332             DoSetItemClientData(pos
, clientData
[i
]); 
 336 void wxCheckListBox::DoSetSelection(int n
, bool select
) 
 338     ListView_SetItemState(GetHwnd(), n
, select 
? LVIS_SELECTED 
: 0, LVIS_SELECTED
); 
 341 bool wxCheckListBox::MSWOnNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
 346     wxCommandEvent 
event(wxEVT_NULL
, m_windowId
); 
 347     event
.SetEventObject(this); 
 349     wxEventType eventType 
= wxEVT_NULL
; 
 351     NMHDR 
*nmhdr 
= (NMHDR 
*)lParam
; 
 353     if ( nmhdr
->hwndFrom 
== GetHwnd() ) 
 355         // almost all messages use NM_LISTVIEW 
 356         NM_LISTVIEW 
*nmLV 
= (NM_LISTVIEW 
*)nmhdr
; 
 358         const int iItem 
= nmLV
->iItem
; 
 360         bool processed 
= true; 
 361         switch ( nmhdr
->code 
) 
 363             case LVN_ITEMCHANGED
: 
 364                 // we translate this catch all message into more interesting 
 365                 // (and more easy to process) wxWidgets events 
 367                 // first of all, we deal with the state change events only and 
 368                 // only for valid items (item == -1 for the virtual list 
 370                 if ( nmLV
->uChanged 
& LVIF_STATE 
&& iItem 
!= -1 ) 
 372                     // temp vars for readability 
 373                     const UINT stOld 
= nmLV
->uOldState
; 
 374                     const UINT stNew 
= nmLV
->uNewState
; 
 376                     // Check image changed 
 377                     if ((stOld 
& LVIS_STATEIMAGEMASK
) != (stNew 
& LVIS_STATEIMAGEMASK
)) 
 379                         event
.SetEventType(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
); 
 380                         event
.SetInt(IsChecked(iItem
)); 
 381                         (void) GetEventHandler()->ProcessEvent(event
); 
 384                     if ( (stNew 
& LVIS_SELECTED
) != (stOld 
& LVIS_SELECTED
) ) 
 386                         eventType 
= wxEVT_COMMAND_LISTBOX_SELECTED
; 
 388                         event
.SetExtraLong( (stNew 
& LVIS_SELECTED
) != 0 ); // is a selection 
 393                 if ( eventType 
== wxEVT_NULL 
) 
 395                     // not an interesting event for us 
 406             return wxControl::MSWOnNotify(idCtrl
, lParam
, result
); 
 410         // where did this one come from? 
 417     event
.SetEventType(eventType
); 
 419     bool processed 
= GetEventHandler()->ProcessEvent(event
);