www.pudn.com > CListCtrlfjs.rar > SortListCtrl.cpp


/******************************************* 
 
             没事儿,尽管用。 
                          --栾义明 
 
*********************************************/ 
 
 
#include "stdafx.h" 
#include "SortListCtrl.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
#define  ID_LIST_PRINT 200 
#define  ID_LIST_SAVE  201 
#define  ID_LIST_DELETE 202 
#define	 ID_LIST_DELETEALL 203 
 
 
LPCTSTR g_pszSection = _T("ListCtrls"); 
 
 
struct ItemData 
{ 
public: 
	ItemData() : arrpsz( NULL ), dwData( NULL ),crText ( NULL ),crBak (NULL),nImage(NULL){} 
 
	LPTSTR* arrpsz; 
	DWORD dwData; 
	//color 
	COLORREF * crText; 
	COLORREF * crBak; 
	int *nImage; 
 
private: 
	// ban copying. 
	ItemData( const ItemData& ); 
	ItemData& operator=( const ItemData& ); 
}; 
 
 
CSortListCtrl::CSortListCtrl() 
	: m_iNumColumns( 0 ) 
	, m_iSortColumn( -1 ) 
	, m_bSortAscending( TRUE ) 
{ 
	m_backcolor=crWindow              = ::GetSysColor(COLOR_WINDOW); 
	m_textcolor=crWindowText          = ::GetSysColor(COLOR_WINDOWFRAME); 
	m_checkbackcolor= crHighLight     = ::GetSysColor(COLOR_HIGHLIGHT); 
	m_checktextcolor= crHighLightText = ::GetSysColor(COLOR_HIGHLIGHTTEXT); 
  
     
	m_checkcolumcolor=m_backcolor; 
    m_OldColumnClick=-1; 
	m_bColumnColorShow=FALSE; 
	m_bExcelShow = FALSE ; 	 
	 
} 
 
 
CSortListCtrl::~CSortListCtrl() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CSortListCtrl, CListCtrl) 
	//{{AFX_MSG_MAP(CSortListCtrl) 
	ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick) 
	ON_WM_DESTROY() 
	ON_WM_RBUTTONDOWN() 
	ON_WM_PAINT() 
	ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) 
	ON_WM_SYSCOLORCHANGE() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CSortListCtrl message handlers 
 
void CSortListCtrl::PreSubclassWindow() 
{ 
	// the list control must have the report style. 
	ASSERT( GetStyle() & LVS_REPORT ); 
 
	CListCtrl::PreSubclassWindow(); 
	m_ctlHeader.SubclassDlgItem (0, this); 
//	VERIFY( m_ctlHeader.SubclassWindow( GetHeaderCtrl()->GetSafeHwnd() ) ); 
} 
 
 
BOOL CSortListCtrl::SetHeadings( UINT uiStringID ) 
{ 
	CString strHeadings; 
	VERIFY( strHeadings.LoadString( uiStringID ) ); 
	return SetHeadings( strHeadings ); 
} 
 
 
// the heading text is in the format column 1 text,column 1 width;column 2 text,column 3 width;etc. 
BOOL CSortListCtrl::SetHeadings( const CString& strHeadings ) 
{ 
	int iStart = 0; 
 
	for( ;; ) 
	{ 
		const int iComma = strHeadings.Find( _T(','), iStart ); 
 
		if( iComma == -1 ) 
			break; 
 
		const CString strHeading = strHeadings.Mid( iStart, iComma - iStart ); 
 
		iStart = iComma + 1; 
 
		int iSemiColon = strHeadings.Find( _T(';'), iStart ); 
 
		if( iSemiColon == -1 ) 
			iSemiColon = strHeadings.GetLength(); 
 
		const int iWidth = atoi( strHeadings.Mid( iStart, iSemiColon - iStart ) ); 
		 
		iStart = iSemiColon + 1; 
 
		if( InsertColumn( m_iNumColumns++, strHeading, LVCFMT_LEFT, iWidth ) == -1 ) 
			return FALSE; 
	 
	} 
  //  UpdateHeadColumn(); 
	return TRUE; 
} 
 
 
int CSortListCtrl::AddItem(LPCTSTR pszText, ... ) 
{ 
	const int iIndex = InsertItem( GetItemCount(), pszText ); 
	LPTSTR* arrpsz = new LPTSTR[ m_iNumColumns ]; 
	COLORREF * clrText = new COLORREF[ m_iNumColumns ]; 
	COLORREF * clrBak= new COLORREF[ m_iNumColumns ]; 
	int * nImage =new int[ m_iNumColumns ]; 
	arrpsz[ 0 ] = new TCHAR[ lstrlen( pszText ) + 1 ]; 
	clrText[ 0 ] = crWindowText; 
	clrBak[ 0 ] = crWindow; 
	nImage[ 0 ] =-1; 
	(void)lstrcpy( arrpsz[ 0 ], pszText ); 
	 
 
 	va_list list; 
	va_start( list, pszText ); 
 
 
	//insert sub item  and set subitem data 
	int iColumn; 
	for( iColumn = 1; iColumn < m_iNumColumns; iColumn++ ) 
	{ 
		pszText = va_arg( list, LPCTSTR ); 
		ASSERT_VALID_STRING( pszText ); 
		VERIFY( CListCtrl::SetItem( iIndex, iColumn, LVIF_TEXT, pszText, 0, 0, 0, 0 ) ); 
 
		arrpsz[ iColumn ] = new TCHAR[ lstrlen( pszText ) + 1 ]; 
		clrText[ iColumn ] = crWindowText; 
		clrBak[ iColumn ] = crWindow; 
		nImage[ iColumn ] =-1; 
 
		(void)lstrcpy( arrpsz[ iColumn ], pszText ); 
 
	} 
 
	va_end( list ); 
 
	VERIFY( SetArray( iIndex, arrpsz,clrText,clrBak,nImage ) ); 
 
	//for(  iColumn = 1; iColumn < m_iNumColumns; iColumn++ ) 
// 
	 
	SetItemColor(iIndex,m_textcolor,m_backcolor); 
	 
	  return iIndex; 
} 
 
 
void CSortListCtrl::FreeItemMemory( const int iItem ) 
{ 
	ItemData* pid = reinterpret_cast( CListCtrl::GetItemData( iItem ) ); 
 
 
 
	LPTSTR* arrpsz = pid->arrpsz; 
 
	for( int i = 0; i < m_iNumColumns; i++ ) 
	{ 
		delete[] arrpsz[ i ];	 
	} 
	delete[] pid->crText; 
	delete[] pid->crBak; 
	delete[] arrpsz; 
	delete pid; 
 
 
	VERIFY( CListCtrl::SetItemData( iItem, NULL ) ); 
} 
 
 
BOOL CSortListCtrl::DeleteItem( int iItem ) 
{ 
	FreeItemMemory( iItem ); 
	return CListCtrl::DeleteItem( iItem ); 
} 
 
 
BOOL CSortListCtrl::DeleteAllItems() 
{ 
	for( int iItem = 0; iItem < GetItemCount(); iItem ++ ) 
		FreeItemMemory( iItem ); 
 
	return CListCtrl::DeleteAllItems(); 
} 
 
 
bool IsNumber( LPCTSTR pszText ) 
{ 
	ASSERT_VALID_STRING( pszText ); 
 
	for( int i = 0; i < lstrlen( pszText ); i++ ) 
		if( !_istdigit( pszText[ i ] ) ) 
			return false; 
 
	return true; 
} 
 
 
int NumberCompare( LPCTSTR pszNumber1, LPCTSTR pszNumber2 ) 
{ 
	ASSERT_VALID_STRING( pszNumber1 ); 
	ASSERT_VALID_STRING( pszNumber2 ); 
 
	const int iNumber1 = atoi( pszNumber1 ); 
	const int iNumber2 = atoi( pszNumber2 ); 
 
	if( iNumber1 < iNumber2 ) 
		return -1; 
	 
	if( iNumber1 > iNumber2 ) 
		return 1; 
 
	return 0; 
} 
 
 
bool IsDate( LPCTSTR pszText ) 
{ 
	ASSERT_VALID_STRING( pszText ); 
 
	// format should be 99/99/9999. 
 
	if( lstrlen( pszText ) != 10 ) 
		return false; 
 
	return _istdigit( pszText[ 0 ] ) 
		&& _istdigit( pszText[ 1 ] ) 
		&& pszText[ 2 ] == _T('/') 
		&& _istdigit( pszText[ 3 ] ) 
		&& _istdigit( pszText[ 4 ] ) 
		&& pszText[ 5 ] == _T('/') 
		&& _istdigit( pszText[ 6 ] ) 
		&& _istdigit( pszText[ 7 ] ) 
		&& _istdigit( pszText[ 8 ] ) 
		&& _istdigit( pszText[ 9 ] ); 
} 
 
 
int DateCompare( const CString& strDate1, const CString& strDate2 ) 
{ 
	const int iYear1 = atoi( strDate1.Mid( 6, 4 ) ); 
	const int iYear2 = atoi( strDate2.Mid( 6, 4 ) ); 
 
	if( iYear1 < iYear2 ) 
		return -1; 
 
	if( iYear1 > iYear2 ) 
		return 1; 
 
	const int iMonth1 = atoi( strDate1.Mid( 3, 2 ) ); 
	const int iMonth2 = atoi( strDate2.Mid( 3, 2 ) ); 
 
	if( iMonth1 < iMonth2 ) 
		return -1; 
 
	if( iMonth1 > iMonth2 ) 
		return 1; 
 
	const int iDay1 = atoi( strDate1.Mid( 0, 2 ) ); 
	const int iDay2 = atoi( strDate2.Mid( 0, 2 ) ); 
 
	if( iDay1 < iDay2 ) 
		return -1; 
 
	if( iDay1 > iDay2 ) 
		return 1; 
 
	return 0; 
} 
 
 
int CALLBACK CSortListCtrl::CompareFunction( LPARAM lParam1, LPARAM lParam2, LPARAM lParamData ) 
{ 
	CSortListCtrl* pListCtrl = reinterpret_cast( lParamData ); 
	ASSERT( pListCtrl->IsKindOf( RUNTIME_CLASS( CListCtrl ) ) ); 
 
	ItemData* pid1 = reinterpret_cast( lParam1 ); 
	ItemData* pid2 = reinterpret_cast( lParam2 ); 
 
	ASSERT( pid1 ); 
	ASSERT( pid2 ); 
 
 
		LPCTSTR pszText1 = pid1->arrpsz[ pListCtrl->m_iSortColumn ]; 
		LPCTSTR pszText2 = pid2->arrpsz[ pListCtrl->m_iSortColumn ]; 
 
 
	ASSERT_VALID_STRING( pszText1 ); 
	ASSERT_VALID_STRING( pszText2 ); 
 
	if( IsNumber( pszText1 ) ) 
		return pListCtrl->m_bSortAscending ? NumberCompare( pszText1, pszText2 ) : NumberCompare( pszText2, pszText1 ); 
	else if( IsDate( pszText1 ) ) 
		return pListCtrl->m_bSortAscending ? DateCompare( pszText1, pszText2 ) : DateCompare( pszText2, pszText1 ); 
	else 
		// text. 
		return pListCtrl->m_bSortAscending ? lstrcmp( pszText1, pszText2 ) : lstrcmp( pszText2, pszText1 ); 
} 
 
 
void CSortListCtrl::OnColumnClick( NMHDR* pNMHDR, LRESULT* pResult ) 
{ 
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; 
	const int iColumn = pNMListView->iSubItem; 
 
	// if it's a second click on the same column then reverse the sort order, 
	// otherwise sort the new column in ascending order. 
 
	Sort( iColumn, iColumn == m_iSortColumn ? !m_bSortAscending : TRUE ); 
     
	if(m_OldColumnClick!=iColumn && m_bColumnColorShow ) 
	{ 
		 
		for(int i=0;i( this ) ) ); 
} 
 
 
void CSortListCtrl::LoadColumnInfo() 
{ 
	// you must call this after setting the column headings. 
	ASSERT( m_iNumColumns > 0 ); 
 
	CString strKey; 
	strKey.Format( _T("%d"), GetDlgCtrlID() ); 
 
	UINT nBytes = 0; 
	BYTE* buf = NULL; 
	if( AfxGetApp()->GetProfileBinary( g_pszSection, strKey, &buf, &nBytes ) ) 
	{ 
		if( nBytes > 0 ) 
		{ 
			CMemFile memFile( buf, nBytes ); 
			CArchive ar( &memFile, CArchive::load ); 
			m_ctlHeader.Serialize( ar ); 
			ar.Close(); 
 
			m_ctlHeader.Invalidate(); 
		} 
 
		delete[] buf; 
	} 
} 
 
 
void CSortListCtrl::SaveColumnInfo() 
{ 
	ASSERT( m_iNumColumns > 0 ); 
 
	CString strKey; 
	strKey.Format( _T("%d"), GetDlgCtrlID() ); 
 
	CMemFile memFile; 
 
	CArchive ar( &memFile, CArchive::store ); 
	m_ctlHeader.Serialize( ar ); 
	ar.Close(); 
 
	DWORD dwLen = memFile.GetLength(); 
	BYTE* buf = memFile.Detach();	 
 
	VERIFY( AfxGetApp()->WriteProfileBinary( g_pszSection, strKey, buf, dwLen ) ); 
 
	free( buf ); 
} 
 
 
void CSortListCtrl::OnDestroy()  
{ 
	for( int iItem = 0; iItem < GetItemCount(); iItem ++ ) 
		FreeItemMemory( iItem ); 
 
	CListCtrl::OnDestroy(); 
} 
 
 
BOOL CSortListCtrl::SetItemText( int nItem, int nSubItem, LPCTSTR lpszText ) 
{ 
	if( !CListCtrl::SetItemText( nItem, nSubItem, lpszText ) ) 
		return FALSE; 
 
	LPTSTR* arrpsz = GetTextArray( nItem ); 
	LPTSTR pszText = arrpsz[ nSubItem ]; 
	delete[] pszText; 
	pszText = new TCHAR[ lstrlen( lpszText ) + 1 ]; 
	(void)lstrcpy( pszText, lpszText ); 
	arrpsz[ nSubItem ] = pszText; 
 
	return TRUE; 
} 
 
 
BOOL CSortListCtrl::SetItemData( int nItem, DWORD dwData ) 
{ 
/* 
		if( nItem >= GetItemCount() ) 
			return FALSE; 
	 
		ItemData* pid = reinterpret_cast( CListCtrl::GetItemData( nItem ) ); 
		ASSERT( pid ); 
		pid->dwData = dwData; 
	 
		return TRUE;*/ 
	CListCtrl::SetItemData( nItem,  dwData); 
	return TRUE; 
	 
} 
 
 
DWORD CSortListCtrl::GetItemData( int nItem ) const 
{ 
 
		ASSERT( nItem < GetItemCount() ); 
	 
		ItemData* pid = reinterpret_cast( CListCtrl::GetItemData( nItem ) ); 
		ASSERT( pid ); 
		return pid->dwData; 
	 
} 
 
 
BOOL CSortListCtrl::SetArray( int iItem, LPTSTR* arrpsz,COLORREF * clrText,COLORREF * clrBak,int * nImage ) 
{ 
	ASSERT( CListCtrl::GetItemData( iItem ) == NULL ); 
	ItemData* pid = new ItemData; 
	pid->arrpsz = arrpsz; 
	pid->crText = clrText; 
	pid->crBak = clrBak; 
	pid->nImage = nImage; 
	return CListCtrl::SetItemData( iItem, reinterpret_cast( pid ) );//set item data / 
} 
 
 
LPTSTR* CSortListCtrl::GetTextArray( int iItem ) const 
{ 
	ASSERT( iItem < GetItemCount() ); 
 
	ItemData* pid = reinterpret_cast( CListCtrl::GetItemData( iItem ) ); 
	return pid->arrpsz; 
} 
 
 
void CSortListCtrl::OnPaint()  
{ 
 
	 
	 
	Default(); 
	CPaintDC dc(this); // device context for painting 
	 
	// TODO: Add your message handler code here 
	 
	// Do not call CListCtrl::OnPaint() for painting messages 
} 
 
void CSortListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) 
{ 
	//draw each item.set txt color,bkcolor.... 
	NMLVCUSTOMDRAW* pLVCD = reinterpret_cast(pNMHDR); 
	 
	// Take the default processing unless we set this to something else below. 
	*pResult = CDRF_DODEFAULT; 
	 
	// First thing - check the draw stage. If it's the control's prepaint 
	// stage, then tell Windows we want messages for every item. 
	 
	if (pLVCD->nmcd.dwDrawStage == CDDS_PREPAINT) 
	{ 
		*pResult = CDRF_NOTIFYITEMDRAW; 
	} 
	else if (pLVCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) 
	{ 
		// This is the notification message for an item.  We'll request 
		// notifications before each subitem's prepaint stage. 
		 
		*pResult = CDRF_NOTIFYSUBITEMDRAW; 
	} 
	else if (pLVCD->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM)) 
	{ 
		// This is the prepaint stage for a subitem. Here's where we set the 
		// item's text and background colors. Our return value will tell 
		// Windows to draw the subitem itself, but it will use the new colors 
		// we set here. 
		 
		int nItem = static_cast (pLVCD->nmcd.dwItemSpec); 
		int nSubItem = pLVCD->iSubItem; 
		 
		ItemData *pXLCD = (ItemData *) pLVCD->nmcd.lItemlParam; 
		ASSERT(pXLCD); 
		 
		COLORREF crText  = m_textcolor;//crWindowText; 
		COLORREF crBkgnd = m_backcolor;//crWindow; 
		 
		int nImage; 
		 
		if (pXLCD){ 
			crText  = (pXLCD->crText)[nSubItem]; 
			crBkgnd = (pXLCD->crBak)[nSubItem]; 
			nImage  = (pXLCD->nImage)[nSubItem]; 
		} 
								 
		 
		 
		// store the colors back in the NMLVCUSTOMDRAW struct 
		pLVCD->clrText = crText; 
		pLVCD->clrTextBk = crBkgnd; 
	//	pLVCD-> = crBkgnd; 
		 
		CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc); 
		CRect rect; 
		GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect); 
		if(nSubItem==0 && m_bExcelShow ) 
		{ 
		     //   CPen pen1,*oldpen; 
                
				rect.left+=1; 
				rect.top+=1; 
				rect.right-=1; 
				rect.bottom-=1; 
				CBrush brush(RGB(100,100,10)),*oldbrush; 
				oldbrush=pDC->SelectObject(&brush); 
				pDC->Rectangle(&rect); 
				pDC->SelectObject(oldbrush); 
				if (GetItemState(nItem, LVIS_SELECTED)) 
					pDC->Draw3dRect(&rect,RGB(10,0,10),RGB(255,230,255));					 
				else 
					pDC->Draw3dRect(&rect,RGB(255,230,255),RGB(10,0,10)); 
		        pDC->SetTextColor(RGB(255,255,255)); 
				CString str; 
				str = GetItemText(nItem, 0); 
				 
				if (!str.IsEmpty())	             
					pDC->DrawText(str,&rect,DT_CENTER | DT_SINGLELINE | DT_VCENTER ); 
               // pDC->SelectObject(oldpen); 
			 
		} 
		else 
		{ 
		 
			if (GetItemState(nItem, LVIS_SELECTED)) 
				DrawText(nItem, nSubItem, pDC,m_checktextcolor,m_checkbackcolor, rect,nImage); 
				//crHighLightText, crHighLight 
			else 
					 
				DrawText(nItem, nSubItem, pDC, crText, crBkgnd, rect,nImage); 
 
			 
		}		 
		*pResult = CDRF_SKIPDEFAULT;	// We've painted everything. 
	} 
} 
 
 
 
 
int CSortListCtrl::AddItemColor(LPCTSTR pszText, COLORREF crText, COLORREF crBak) 
{ 
	//insert item at the last 
	const int iIndex = InsertItem( GetItemCount(), pszText ); 
	ItemData *m_pSortItemData=new ItemData[GetColumns()]; 
/* 
	m_pSortItemData[0].crText=crText; 
	m_pSortItemData[0].crBak=crBak; 
*/ 
	 
	SetItemData(iIndex,(DWORD) m_pSortItemData); 
 
	//no sort function 
	 
	return iIndex; 
 
 
} 
 
int CSortListCtrl::GetColumns() 
{ 
	return m_ctlHeader.GetItemCount(); 
 
} 
 
BOOL CSortListCtrl::GetSubItemRect(int nItem, int nSubItem, int nArea, CRect &rect) 
{ 
 
	ASSERT(nItem >= 0); 
	ASSERT(nItem < GetItemCount()); 
	if ((nItem < 0) || nItem >= GetItemCount()) 
		return FALSE; 
	ASSERT(nSubItem >= 0); 
	ASSERT(nSubItem < GetColumns()); 
	if ((nSubItem < 0) || nSubItem >= GetColumns()) 
		return FALSE; 
	 
	BOOL bRC = CListCtrl::GetSubItemRect(nItem, nSubItem, nArea, rect); 
	 
	// if nSubItem == 0, the rect returned by CListCtrl::GetSubItemRect 
	// is the entire row, so use left edge of second subitem 
	 
	if (nSubItem == 0) 
	{ 
		if (GetColumns() > 1) 
		{ 
			CRect rect1; 
			bRC = GetSubItemRect(nItem, 1, LVIR_BOUNDS, rect1); 
			rect.right = rect1.left; 
		} 
	} 
	 
	return bRC; 
 
} 
 
 
 
 
 
void CSortListCtrl::DrawText(int nItem, int nSubItem, CDC *pDC, COLORREF crText, COLORREF crBkgnd, CRect &rect,int nImage) 
{ 
	ASSERT(pDC); 
	 
//	GetDrawColors(nItem, nSubItem, crText, crBkgnd); 
	 
	pDC->FillSolidRect(&rect, crBkgnd); 
	 
	CString str; 
	str = GetItemText(nItem, nSubItem); 
	 
	if (!str.IsEmpty()) 
	{ 
		// get text justification 
		HDITEM hditem; 
		hditem.mask = HDI_FORMAT; 
		m_ctlHeader.GetItem(nSubItem, &hditem); 
		int nFmt = hditem.fmt & HDF_JUSTIFYMASK; 
		UINT nFormat = DT_VCENTER | DT_SINGLELINE; 
		if (nFmt == HDF_CENTER) 
			nFormat |= DT_CENTER; 
		else if (nFmt == HDF_LEFT) 
			nFormat |= DT_LEFT; 
		else 
			nFormat |= DT_RIGHT; 
		 
		if(nImage!=-1) 
		{ 
			CPoint pt; 
			pt.x=rect.left+2; 
			pt.y=rect.top+2; 
			GetImageList(1)->Draw(pDC,nImage,pt,ILD_TRANSPARENT); 
			 
			rect.left+=30; 
		} 
		else 
			rect.left+=5; 
		pDC->SetBkMode(TRANSPARENT); 
		pDC->SetTextColor(crText); 
		pDC->SetBkColor(crBkgnd); 
		pDC->DrawText(str, &rect, nFormat); 
	 
	} 
 
} 
 
 
 
void CSortListCtrl::OnSysColorChange()  
{ 
	CListCtrl::OnSysColorChange(); 
	 
	// TODO: Add your message handler code here 
 
	crWindow              = ::GetSysColor(COLOR_WINDOW); 
	crWindowText          = ::GetSysColor(COLOR_WINDOWTEXT); 
	crHighLight     = ::GetSysColor(COLOR_HIGHLIGHT); 
	crHighLightText = ::GetSysColor(COLOR_HIGHLIGHTTEXT); 
	 
	 
 
	 
} 
 
void CSortListCtrl::SetItemColor(int nItem, int nSubItem, COLORREF clrText, COLORREF clrBkgnd) 
{ 
	ASSERT(nItem >= 0); 
	ASSERT(nItem < GetItemCount()); 
	if ((nItem < 0) || nItem >= GetItemCount()) 
		return ; 
	ASSERT(nSubItem >= 0); 
	ASSERT(nSubItem < GetColumns()); 
	if ((nSubItem < 0) || nSubItem >= GetColumns()) 
		return ; 
	 
	 
	if (nItem < 0) 
		return ; 
	 
	 
	ItemData *pid = (ItemData *) CListCtrl::GetItemData(nItem); 
	if (pid) 
	{ 
		(pid->crText)[nSubItem]		 = (clrText == -1) ? crWindowText : clrText; 
		(pid->crBak)[nSubItem]		 = (clrBkgnd == -1) ? crWindow : clrBkgnd; 
	} 
	 
	UpdateSubItem(nItem, nSubItem); 
 
} 
 
void CSortListCtrl::UpdateSubItem(int nItem, int nSubItem) 
{ 
	ASSERT(nItem >= 0); 
				ASSERT(nItem < GetItemCount()); 
				if ((nItem < 0) || nItem >= GetItemCount()) 
					return; 
				ASSERT(nSubItem >= 0); 
				ASSERT(nSubItem < GetColumns()); 
				if ((nSubItem < 0) || nSubItem >= GetColumns()) 
					return; 
				 
				CRect rect; 
				if (nSubItem == -1) 
				{ 
					GetItemRect(nItem, &rect, LVIR_BOUNDS); 
					//GetDC()->Draw3dRect(&rect,RGB(255,0,0),RGB(0,255,0)); 
				} 
				else 
				{ 
					GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect); 
				} 
				 
				InvalidateRect(&rect); 
				UpdateWindow(); 
				 
				 
} 
 
void CSortListCtrl::SetCustomColor(COLORREF textcolor, COLORREF backcolor, COLORREF checkcolumcolor, COLORREF checktextcolor, COLORREF checkbackcolor) 
{ 
	m_textcolor=textcolor; 
	m_backcolor=backcolor; 
	m_checkcolumcolor=checkcolumcolor; 
	m_checktextcolor=checktextcolor; 
	m_checkbackcolor=checkbackcolor; 
	for(int i=0;i=0;j--) 
	  m_ctlHeader.SetSortArrow(j,1); 
 
} 
 
void CSortListCtrl::SetItemColor(int nItem, COLORREF clrText, COLORREF clrBkgnd) 
{ 
   for(int j=0;j= 0); 
	ASSERT(nItem < GetItemCount()); 
	if ((nItem < 0) || nItem >= GetItemCount()) 
		return ; 
	ASSERT(nSubItem >= 0); 
	ASSERT(nSubItem < GetColumns()); 
	if ((nSubItem < 0) || nSubItem >= GetColumns()) 
		return ; 
	if(nImage>GetImageList(1)->GetImageCount()) 
		return; 
	 
	if (nItem < 0) 
		return ; 
	 
	 
	ItemData *pid = (ItemData *) CListCtrl::GetItemData(nItem); 
	if (pid) 
	{ 
		(pid->nImage)[nSubItem]	 = nImage; 
 
	} 
	 
	UpdateSubItem(nItem, nSubItem); 
 
 
} 
 
void CSortListCtrl::SetHeadImage(UINT back, UINT asc, UINT dec) 
{ 
//	m_ctlHeader.SetImage(back,asc,dec); 
} 
 
BOOL CSortListCtrl::SetExcelShow(BOOL bShow) 
{ 
 
	BOOL bOld=m_bExcelShow; 
	m_bExcelShow=bShow; 
	Invalidate(); 
	return bOld; 
}