www.pudn.com > virtualListview_demo.zip > MyListCtrl.cpp


// MyListCtrl.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "listview_example.h" 
#include "MyListCtrl.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CMyListCtrl 
 
int column_sort = 0; 
BOOL bSortAscending = FALSE; 
 
CMyListCtrl::CMyListCtrl() 
{ 
	array = NULL; 
	count = 0; 
	max_items = 0; 
} 
 
CMyListCtrl::~CMyListCtrl() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl) 
	//{{AFX_MSG_MAP(CMyListCtrl) 
	ON_WM_CREATE() 
	ON_WM_DESTROY() 
	ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick) 
	ON_NOTIFY_REFLECT(LVN_GETDISPINFO, OnGetdispinfo) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CMyListCtrl message handlers 
 
//add a single item into the array for viewing 
void CMyListCtrl::AddItem(DATA *item) 
{ 
	if(item == NULL) 
		return; 
 
	if(count >= max_items)	//time to realloc() some more 
	{ 
		//we'll ask for another 500 spaces 
		//You can realloc() more or less if you want. 
		//The obvious tradeoff is speed versus memory requirements. 
 
		DATA **tempptr; 
		int newmax; 
 
		newmax = max_items + 500; 
		tempptr = (DATA**)realloc(array, ((sizeof(DATA*)*newmax))); 
		if(tempptr == NULL) 
		{ 
			MessageBox("Running out of memory..."); 
			return; 
		} 
 
		array = tempptr; 
		max_items = newmax; 
	} 
 
	array[count++] = item; 
	//force redraw 
	SetItemCount(count); 
} 
 
//add x number of items into view 
void CMyListCtrl::AddItem(DATA *front, int numToInsert) 
{ 
	if(front == NULL || numToInsert <= 0) 
		return; 
 
	int freespace = max_items - count; 
 
	//realloc() more if needed. 
	if(freespace < numToInsert) 
	{ 
		int newmax = max_items + (numToInsert - freespace); 
		DATA **tempptr; 
 
		tempptr = (DATA**)realloc(array, ((sizeof(DATA*)*newmax))); 
		if(tempptr == NULL) 
		{ 
			MessageBox("Running out of memory..."); 
			return; 
		} 
 
		array = tempptr; 
		max_items = newmax; 
	} 
 
	int i; 
	DATA *tempptr = front; 
 
	//fill in array. if we made it this far, we have enough room in the array. 
	for(i = 0; i < numToInsert; i++) 
	{ 
		array[count++] = tempptr; 
		tempptr = tempptr->next; 
	} 
 
	//force redraw 
	SetItemCount(count); 
} 
 
int CMyListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
	if (CListCtrl::OnCreate(lpCreateStruct) == -1) 
		return -1; 
 
	//start off with enough room to hold 500 items. We will realloc() more room later as needed. 
	//for better performance gains (but more required memory) start off with a larger limit. 
	array = (DATA**)malloc(sizeof(DATA*) * 500); 
	if(array) 
		ZeroMemory(array, (sizeof(DATA*) * 500)); 
	else 
		return -1; 
 
	max_items = 500; 
 
	return 0; 
} 
 
void CMyListCtrl::OnDestroy()  
{ 
	CListCtrl::OnDestroy(); 
	if(array) 
		free(array); 
} 
 
//comparison function 
int	SortFunc(const void *v1, const void *v2) 
{ 
	DATA **nn1, **nn2, *n1, *n2; 
	int equal = 0; 
 
	nn1 = (DATA **)v1; 
	nn2 = (DATA **)v2; 
 
	n1 = (DATA*)*nn1; 
	n2 = (DATA*)*nn2; 
 
	if(n1 == NULL || n2 == NULL) 
		return 0; 
 
	switch(column_sort) 
	{ 
	case 0: 
		equal = strcmp(n1->field1, n2->field1); 
		break; 
 
	case 1: 
		equal = strcmp(n1->field2, n2->field2); 
		break; 
 
	case 2: 
		equal = strcmp(n1->field3, n2->field3); 
		break; 
	} 
 
	if(bSortAscending == FALSE) 
		equal *= -1; 
 
	return equal; 
} 
 
//user clicked a column. sort by header in ascending or descending order 
void CMyListCtrl::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; 
	int clicked = pNMListView->iSubItem; 
 
	if(column_sort == clicked) 
		bSortAscending = !bSortAscending; 
	else 
	{ 
		column_sort = clicked; 
		bSortAscending = TRUE; 
	} 
 
	qsort(array, count, sizeof(DATA*), SortFunc); 
	SetItemCount(count);	//force redraw 
 
	*pResult = 0; 
} 
 
//Windows is asking for the text to display, at item(iItemIndex), subitem(pItem->iSubItem) 
void CMyListCtrl::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; 
 
	LV_ITEM* pItem= &(pDispInfo)->item; 
	int iItemIndex= pItem->iItem; 
	DATA *ptr = array[iItemIndex]; 
 
	if(pItem->mask & LVIF_TEXT) 
	{ 
		if(pItem->iSubItem == 0)	//field 1 
			lstrcpyn(pItem->pszText, ptr->field1, pItem->cchTextMax); 
		else 
		if(pItem->iSubItem == 1)	//field 2 
			lstrcpyn(pItem->pszText, ptr->field2, pItem->cchTextMax); 
		else 
		if(pItem->iSubItem == 2)	//field 3 
			lstrcpyn(pItem->pszText, ptr->field3, pItem->cchTextMax); 
	} 
 
	*pResult = 0; 
}