Smart ATL/WTL combo box and list view classes to cast and optionally manage typed control item data

Inspired by the post on Yahoo’s WTL group (actually, I have been going to post on this topic for a couple of weeks already).

Standard Windows controls (including common controls) that have multiple items (list box, combo box, list view, tree view etc.) have an option to attach user defined value of type DWORD_PTR (LPARAM) to each item. This is quite sufficient when using controls, however type cast to and from DWORD_PTR is required with most control item data operations.

CAiComboBoxT and CAiListViewT classes templates redefine GetItemData/SetItemData methods to perform automatic type casts. An optional template class CAiListControlDataTraitsT does even more: it manages per-item definted item data class in contained CAtlList collection and attached a pointer to item data class to each control item.

The classes may be used as follows:

CAiComboBoxT < CComboBoxItemData* > m_ComboBox;
CAiListViewT < CListViewItemData, CAiListControlDataTraitsT > m_ListView;

m_ComboBox is a combo box window class (CComboBox descendant) with CComboBoxItemData pointer defined as control item data.

m_ListView is a list view class (CListViewCtrl descendant) with CListViewItemData defined as control item data. CListViewItemData instances are managed by control class using CAtlList collection (and a position in the collection is actually casted to DWORD_PTR and set as lower level control item data).

20-image001.png

To access item class data, you need the following lines of code:

CComboBoxItemData* pComboBoxItemData = m_ComboBox.GetItemData(nItem); // INT nItem
CListViewItemData& ListViewItemData = m_ListView.GetItemData(nItem); // INT nItem

Sample project below illustrates basic usage of the classes:

BEGIN_MSG_MAP_EX(CMainDialog)
MSG_WM_INITDIALOG(OnInitDialog)

COMMAND_HANDLER_EX(IDC_COMBOBOX, CBN_SELENDOK, OnComboBoxSelEndOk)
MSG_LVN_GETDISPINFO(IDC_LISTVIEW, OnListGetDispInfo)
MSG_LVN_DBLCLK(IDC_LISTVIEW, OnListViewDblClk)

OnInitDialog initializes classes including control item data initialization, OnComboBoxSelEndOk obtains currently selected combo box item data class pointer (not managed by the window class), OnListGetDispInfo accesses managed control item data pointer, OnListViewDblClk retrieves first selected control item data class pointer to show message box.

Keywords: DWORD_PTR, CB_GETITEMDATA, CB_SETITEMDATA, LVM_GETITEM, LVM_SETITEM

Visual C++.NET 2005 source code can be downloaded here, compiled binary – here.

Update 2012-07-24:

Visual C++ 2010 .h file: /trac/public/browser/…/rowtlcrack.h

Code snippet:

https://www.alax.info/trac/public/browser/trunk/Utilities/LogProcessExceptions/MainWizard.h#L104

BEGIN_MSG_MAP_EX(CProcessPropertyPage)
    CHAIN_MSG_MAP(CWizardPropertyPageT<CProcessPropertyPage>)
    MSG_WM_INITDIALOG(OnInitDialog)
    MSG_LVN_GETDISPINFO(IDC_MAIN_PROCESSES, OnProcessListViewGetDispInfo)
    MSG_LVN_GETINFOTIP(IDC_MAIN_PROCESSES, OnProcessListViewGetInfoTip)
    MSG_LVN_ITEMCHANGED(IDC_MAIN_PROCESSES, OnProcessListItemChanged)
    MSG_LVN_DBLCLK(IDC_MAIN_PROCESSES, OnProcessListViewDblClk)
    COMMAND_ID_HANDLER_EX(IDC_MAIN_REFRESHPROCESSES, OnRefreshButtonClicked)
    REFLECT_NOTIFICATIONS()
END_MSG_MAP()

https://www.alax.info/trac/public/browser/trunk/Utilities/LogProcessExceptions/MainWizard.h#L579

LRESULT OnProcessListViewGetInfoTip(NMLVGETINFOTIP* pHeader)
{
    const CProcessData& ProcessData = m_ProcessDataList.GetAt(m_ProcessListView.GetItemData(pHeader->iItem));
    CString& sTextBuffer = m_ProcessListView.GetTextBufferString(TRUE);
    sTextBuffer.AppendFormat(_T("File Name: %s\r\n"), ProcessData.GetFileName());
    sTextBuffer.AppendFormat(_T("Identifier: %d (0x%x)\r\n"), ProcessData.m_nIdentifier, ProcessData.m_nIdentifier);
    BOOL bIs64Bit = FALSE;
    #if !defined(_WIN64)
    if(SafeIsWow64Process())
    #endif // !defined(_WIN64)
    bIs64Bit = !ProcessData.m_bIsWow64;
    sTextBuffer.AppendFormat(_T("Type: %s\r\n"), !bIs64Bit ? _T("32-bit") : _T("64-bit"));
    if(!ProcessData.m_sAccount.IsEmpty())
    sTextBuffer.AppendFormat(_T("Account: %s\r\n"), ProcessData.m_sAccount);
    sTextBuffer.AppendFormat(_T("Window Caption: %s\r\n"), ProcessData.m_sWindowCaption);
    //sTextBuffer.AppendFormat(_T("Image File Path: %s\r\n"), ProcessData.GetImageFilePath());
    sTextBuffer.AppendFormat(_T("Working Set Size: %s MB\r\n"), _StringHelper::FormatNumber((LONG) ProcessData.GetMemoryCounters().WorkingSetSize >> 20));
    sTextBuffer.AppendFormat(_T("Private Memory: %s MB\r\n"), _StringHelper::FormatNumber((LONG) ProcessData.GetMemoryCounters().PrivateUsage >> 20));
    sTextBuffer.TrimRight(_T("\t\n\r ."));
    _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, m_ProcessListView.GetTextBuffer(), _TRUNCATE);
    return 0;
}

3 Replies to “Smart ATL/WTL combo box and list view classes to cast and optionally manage typed control item data”

  1. This code, along with some of your other WTL classes are still quite useful, but they don’t seem to be available in your SVN repositories and the old download links no longer work. Is there any chance you could put them back online? Thanks!

Leave a Reply