// ListCtrlEx.cpp : implementation file
//
#include "stdafx.h"
#include "ListCtrlEx.h"
CListCtrlEx::EditorInfo::EditorInfo()
:m_pfnInitEditor(NULL)
,m_pfnEndEditor(NULL)
,m_pWnd(NULL)
,m_bReadOnly(false)
{
}
CListCtrlEx::EditorInfo::EditorInfo(PFNEDITORCALLBACK pfnInitEditor, PFNEDITORCALLBACK pfnEndEditor, CWnd *pWnd)
:m_pfnInitEditor(pfnInitEditor)
,m_pfnEndEditor(pfnEndEditor)
,m_pWnd(pWnd)
,m_bReadOnly(false)
{
}
CListCtrlEx::CellInfo::CellInfo(int nColumn)
:m_clrBack(-1)
,m_clrText(-1)
,m_dwUserData(NULL)
,m_nColumn(nColumn)
{
}
CListCtrlEx::CellInfo::CellInfo(int nColumn, COLORREF clrBack, COLORREF clrText, DWORD_PTR dwUserData)
:m_clrBack(clrBack)
,m_clrText(clrText)
,m_dwUserData(dwUserData)
,m_nColumn(nColumn)
{
}
CListCtrlEx::CellInfo::CellInfo(int nColumn, EditorInfo eiEditor, COLORREF clrBack, COLORREF clrText, DWORD_PTR dwUserData)
:m_clrBack(clrBack)
,m_clrText(clrText)
,m_dwUserData(dwUserData)
,m_eiEditor(eiEditor)
,m_nColumn(nColumn)
{
}
CListCtrlEx::CellInfo::CellInfo(int nColumn, EditorInfo eiEditor, DWORD_PTR dwUserData)
:m_clrBack(-1)
,m_clrText(-1)
,m_dwUserData(dwUserData)
,m_eiEditor(eiEditor)
,m_nColumn(nColumn)
{
}
CListCtrlEx::ColumnInfo::ColumnInfo(int nColumn)
:m_eiEditor()
,m_clrBack(-1)
,m_clrText(-1)
,m_nColumn(nColumn)
,m_eSort(None)
,m_eCompare(NotSet)
,m_fnCompare(NULL)
{
}
CListCtrlEx::ColumnInfo::ColumnInfo(int nColumn, PFNEDITORCALLBACK pfnInitEditor, PFNEDITORCALLBACK pfnEndEditor, CWnd *pWnd)
:m_eiEditor(pfnInitEditor, pfnEndEditor, pWnd)
,m_nColumn(nColumn)
,m_clrBack(-1)
,m_clrText(-1)
,m_eSort(None)
,m_eCompare(NotSet)
,m_fnCompare(NULL)
{
}
CListCtrlEx::ItemData::ItemData(DWORD_PTR dwUserData)
:m_clrBack(0xFFFFFFFF)
,m_clrText(0xFFFFFFFF)
,m_dwUserData(dwUserData)
{
}
CListCtrlEx::ItemData::ItemData(COLORREF clrBack, COLORREF clrText, DWORD_PTR dwUserData)
:m_clrBack(clrBack)
,m_clrText(clrText)
,m_dwUserData(dwUserData)
{
}
CListCtrlEx::ItemData::~ItemData()
{
while(m_aCellInfo.GetCount()>0)
{
CellInfo *pInfo = (CellInfo*)m_aCellInfo.GetAt(0);
m_aCellInfo.RemoveAt(0);
delete pInfo;
}
}
// CListCtrlEx
IMPLEMENT_DYNAMIC(CListCtrlEx, CListCtrl)
CListCtrlEx::CListCtrlEx()
:m_pEditor(NULL)
,m_nEditingRow(-1)
,m_nEditingColumn(-1)
,m_msgHook()
,m_nRow(-1)
,m_nColumn(-1)
,m_bHandleDelete(FALSE)
,m_nSortColumn(-1)
,m_fnCompare(NULL)
,m_hAccel(NULL)
,m_dwSortData(NULL)
, m_bInvokeAddNew(FALSE)
{
#ifndef _WIN32_WCE
EnableActiveAccessibility();
#endif
}
#define ID_EDITOR_CTRL 5000
CListCtrlEx::~CListCtrlEx()
{
DeleteAllItemsData();
DeleteAllColumnInfo();
}
BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
ON_NOTIFY_REFLECT_EX(NM_DBLCLK, &CListCtrlEx::OnNMDblclk)
ON_NOTIFY_REFLECT_EX(NM_CUSTOMDRAW, &CListCtrlEx::OnNMCustomdraw)
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, &CListCtrlEx::OnHdnItemclick)
END_MESSAGE_MAP()
// CListCtrlEx message handlers
// Retrieves the data (lParam) associated with a particular item.
DWORD_PTR CListCtrlEx::GetItemData(int nItem) const
{
ItemData* pData = (ItemData*)GetItemDataInternal(nItem);
if(!pData) return NULL;
return pData->m_dwUserData;
}
// Retrieves the data (lParam) associated with a particular item.
DWORD_PTR CListCtrlEx::GetItemDataInternal(int nItem) const
{
return CListCtrl::GetItemData(nItem);
}
int CListCtrlEx::InsertItem(int nItem, LPCTSTR lpszItem)
{
int ret = CListCtrl::InsertItem(nItem, lpszItem);
SetItemData(ret, 0);
return ret;
}
int CListCtrlEx::InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
{
int ret = CListCtrl::InsertItem(nItem, lpszItem, nImage);
SetItemData(ret, 0);
return ret;
}
int CListCtrlEx::InsertItem(const LVITEM* pItem)
{
int ret = 0;
LVITEM pI = *pItem;
if(pItem && (pItem->mask & LVIF_PARAM))
{
pI.mask &= (~LVIF_PARAM);
}
ret = CListCtrl::InsertItem(&pI);
SetItemData(ret, pItem->lParam);
return ret;
}
// Sets the data (lParam) associated with a particular item.
BOOL CListCtrlEx::SetItemData(int nItem, DWORD_PTR dwData)
{
ItemData* pData = (ItemData*)GetItemDataInternal(nItem);
if(!pData)
{
pData = new ItemData(dwData);
m_aItemData.Add(pData);
}
else
pData->m_dwUserData = dwData;
return CListCtrl::SetItemData(nItem, (DWORD_PTR)pData);
}
// Removes a single item from the control.
BOOL CListCtrlEx::DeleteItem(int nItem)
{
DeleteItemData(nItem);
return CListCtrl::DeleteItem(nItem);
}
// Removes all items from the control.
BOOL CListCtrlEx::DeleteAllItems()
{
int nCount = this->GetItemCount();
DeleteAllItemsData();
return CListCtrl::DeleteAllItems();
}
BOOL CListCtrlEx::DeleteAllItemsData( )
{
while(m_aItemData.GetCount()>0)
{
ItemData* pData = (ItemData*)m_aItemData.GetAt(0);
if(pData) delete pData;
m_aItemData.RemoveAt(0);
}
return TRUE;
}
BOOL CListCtrlEx::DeleteItemData(int nItem)
{
if(nItem < 0 || nItem > GetItemCount()) return FALSE;
ItemData* pData = (ItemData*)CListCtrl::GetItemData(nItem);
INT_PTR nCount = m_aItemData.GetCount();
for(INT_PTR i = 0; i < nCount && pData; i++)
{
if(m_aItemData.GetAt(i) == pData)
{
m_aItemData.RemoveAt(i);
break;
}
}
if(pData) delete pData;
return TRUE;
}
BOOL CListCtrlEx::DeleteAllColumnInfo( )
{
while(m_aColumnInfo.GetCount()>0)
{
ColumnInfo* pData = (ColumnInfo*)m_aColumnInfo.GetAt(0);
if(pData) delete pData;
m_aColumnInfo.RemoveAt(0);
}
return TRUE;
}
BOOL CListCtrlEx::DeleteColumnInfo(int nColumn)
{
if(nColumn < 0 || nColumn > GetColumnCount()) return FALSE;
ColumnInfo* pData = (ColumnInfo*)GetColumnInfo(nColumn);
INT_PTR nCount = m_aColumnInfo.GetCount();
for(INT_PTR i = 0; i < nCount && pData; i++)
{
if(m_aColumnInfo.GetAt(i) == pData)
{
m_aColumnInfo.RemoveAt(i);
break;
}
}
if(pData) delete pData;
return TRUE;
}
void CListCtrlEx::SetColumnEditor(int nColumn, PFNEDITORCALLBACK pfnInitEditor, PFNEDITORCALLBACK pfnEndEditor, CWnd* pWnd)
{
ColumnInfo* pColInfo = GetColumnInfo(nColumn);
if(!pColInfo)
{
pColInfo = new ColumnInfo(nColumn);
m_aColumnInfo.Add(pColInfo);
}
pColInfo->m_eiEditor.m_pfnInitEditor = pfnInitEditor;
pColInfo->m_eiEditor.m_pfnEndEditor = pfnEndEditor;
pColInfo->m_eiEditor.m_pWnd = pWnd;
}
void CListCtrlEx::SetColumnEditor(int nColumn, CWnd* pWnd)
{
SetColumnEditor(nColumn, NULL, NULL, pWnd);
}
void CListCtrlEx::SetRowEditor(int nRow, CWnd* pWnd)
{
SetRowEditor(nRow, NULL, NULL, pWnd);
}
void CListCtrlEx::SetRowEditor(int nRow, PFNEDITORCALLBACK pfnInitEditor, PFNEDITORCALLBACK pfnEndEditor, CWnd* pWnd)
{
ItemData* pData = (ItemData*)GetItemDataInternal(nRow);
if(!pData)
{
SetItemData(nRow, 0);
pData = (ItemData*)GetItemDataInternal(nRow);
}
pData->m_eiEditor.m_pfnInitEditor = pfnInitEditor;
pData->m_eiEditor.m_pfnEndEditor = pfnEndEditor;
pData->m_eiEditor.m_pWnd = pWnd;
}
CListCtrlEx::ColumnInfo* CListCtrlEx::GetColumnInfo(int nColumn)
{
INT_PTR nCount = m_aColumnInfo.GetCount();
for(INT_PTR i = 0; i < nCount; i++)
{
ColumnInfo* pColInfo = (ColumnInfo*)m_aColumnInfo.GetAt(i);
if(pColInfo->m_nColumn == nColumn) return pColInfo;
}
return NULL;
}
int CListCtrlEx::FindItem(LVFINDINFO* pFindInfo, int nStart ) const
{
if(pFindInfo->flags & LVIF_PARAM)
{
int nCount = GetItemCount();
for(int i = nStart+1; i < nCount; i++)
{
if(pFindInfo->lParam == GetItemData(i)) return i;
}
return -1;
}
else
{
return CListCtrl::FindItem(pFindInfo, nStart);
}
}
int CListCtrlEx::GetItemIndexFromData(DWORD_PTR dwData)
{
LVFINDINFO find;
find.flags = LVFI_PARAM;
find.lParam = dwData;
return CListCtrl::FindItem(&find);
}
int CALLBACK CListCtrlEx::CompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
CListCtrlEx *This = reinterpret_cast<CListCtrlEx*>(lParamSort);
ColumnInfo *pColInfo;