Click here to Skip to main content
15,898,222 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi,
I need sort a list view control by string column.
I knew message LVM_SORTITEMS.
and have compare function

So
1. I must copy all items to string array
2. Set to all items lparam to index of the array
3. Send message LVM_SORTITEMS

C++
char myArray[100][MAX_PATH]; //for example static array for store

int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort){
   int ind_1 = int( lParam1 );
   int ind_2 = int( lParam2 );
   return lstrcmp( myArray[ind_1], myArray[ind_2]);
}

OK or this is wrong way?
Posted
Updated 30-Aug-19 10:21am
v2

When I need to do it, I use the lParam of each item added to the listView to point to the struct that contains the item itself. This way, when in the compare function, you can simply use the two lParam values to access all of the data that each item in the listView represents.
This allows you (for instance) to use the lParamSort param as a way of telling your sorting function how to behave. I often use this to designate the column I'd like to base the sort on, using negative or positive to designate the direction.

Here's an addItems func and the sortFunc that goes with that listView



C++
/////// Example Add items to lisstView ////////
    if (numItems != 0)
    {
        HWND lvWnd = GetDlgItem(mainDlgHwnd, IDC_ITEM_LIST);

        clearListView(lvWnd);
        for (int i=0; i<numitems;>        {
            addListViewItem(lvWnd,
                            (char*)makeNiceDate(curFeedItems[i].pubdate).c_str(),
                            (char*)curFeedItems[i].title.c_str(),
                            (char*)curFeedItems[i].author.c_str(),
                            (LPARAM)&curFeedItems[i]);
        }
    }

/////// Example sort ////////
	lParamSort = 1 + nSortColumn;
	if (!bSortAscending)
		lParamSort = -lParamSort;

	// sort list
	ListView_SortItems(pLVInfo->hdr.hwndFrom, myCompFunc, lParamSort);




typedef struct
{
    string title;
    string description;
    string link;
    string author;
    string pubdate;
    string subject;
} rssItem_t;



void addListViewItem(HWND listView, char *timeStr, char *titleStr, char *authorStr, LPARAM ptrToInRssItem)
{
    LV_ITEM newItem;
    int insertIndex;

    insertIndex = ListView_GetItemCount(listView);

    newItem.mask = LVIF_TEXT|LVIF_PARAM;
    newItem.iItem = insertIndex;
    newItem.pszText = timeStr;
    newItem.cchTextMax = strlen(timeStr);
    newItem.iSubItem = 0;
    newItem.lParam = ptrToInRssItem;
    insertIndex = SendMessage(listView, LVM_INSERTITEM, 0, (LPARAM)&newItem);

    newItem.mask = LVIF_TEXT;
    newItem.pszText = titleStr;
    newItem.cchTextMax = strlen(titleStr);
    newItem.iSubItem = 1;
    SendMessage(listView, LVM_SETITEM, 0, (LPARAM)&newItem);

    newItem.mask = LVIF_TEXT;
    newItem.pszText = authorStr;
    newItem.cchTextMax = strlen(authorStr);
    newItem.iSubItem = 2;
    SendMessage(listView, LVM_SETITEM, 0, (LPARAM)&newItem);
}








int CALLBACK myCompFunc(LPARAM lp1, LPARAM lp2, LPARAM sortParam)
{
    bool isAsc = (sortParam > 0);
    int column = abs(sortParam)-1;
    rssItem_t *item1, *item2;

    item1 = (rssItem_t*) lp1;
    item2 = (rssItem_t*) lp2;
    switch (column)
    {
        case 0:
            if (isAsc) return parseDateStr(item1->pubdate) - parseDateStr(item2->pubdate);
            else return parseDateStr(item2->pubdate) - parseDateStr(item1->pubdate);
            break;

        case 1:
            if (isAsc) return strcasecmp(item1->title.c_str(), item2->title.c_str());
            else return strcasecmp(item2->title.c_str(), item1->title.c_str());

        case 2:
            if (isAsc) return strcasecmp(item1->author.c_str(), item2->author.c_str());
            else return strcasecmp(item2->author.c_str(), item1->author.c_str());
            break;
    }
    return 0;
}
 
Share this answer
 
// Global
int g_iNumColumns;
int g_iSortColumn;
BOOL g_bSortAscending;
static int CALLBACK CompareFunction( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort );


void CDlgListCtrl::OnColumnclickListCtrlAnalysis(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	// TODO: Add your control notification handler code here

	const int iColumn = pNMLV->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 == g_iSortColumn ? !g_bSortAscending : TRUE );

	*pResult = 0;
}


void CDlgListCtrl::Sort( int iColumn, BOOL bAscending )
{
	// Globo values used because the CALLBACK CompareFunction must be defined outside of the Class. 
	g_iSortColumn = iColumn;
	g_bSortAscending = bAscending;

	LVITEM lvItem;
	int n;

	for(n = 0; n < m_list_ctrl_analysis.GetItemCount(); n++ )
		{
			lvItem.mask = LVIF_PARAM;
//SortItems uses the lvItem.lParam to sort the CListCtrl 
//The lParam1 parameter is the 32-bit value associated with the first item that is 
// compared, and lParam2 parameter is the value associated with the second 
// item.
// The lParam1 and lParam2 were made the sames as the current nitem numbers for the 
// current ListCtrl table each time the column header is clicked to new sort.
			lvItem.lParam = (LPARAM)n;
			lvItem.iItem = n;
			lvItem.iSubItem = 0;

			m_list_ctrl_analysis.SetItem(&lvItem);
		}

	m_list_ctrl_analysis.SortItems( CompareFunction, (LPARAM)&m_list_ctrl) ; 
                                      // Or whatever you named your CListCtrl	
	}
	


int CALLBACK CompareFunction( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
{
	CListCtrl* pListCtrl = (CListCtrl*) lParamSort;
	int result;
 
	
	CString    strItem1 = pListCtrl->GetItemText(static_cast<int>(lParam1), g_iSortColumn);
    CString    strItem2 = pListCtrl->GetItemText(static_cast<int>(lParam2), g_iSortColumn);
   
// Add your own fancy comparison technique here, such as the date/time string. 

	if( g_bSortAscending == TRUE )
		result = strcmp(CStringA(strItem1), CStringA(strItem2));

	if( g_bSortAscending == FALSE )
		result = strcmp(CStringA(strItem2), CStringA(strItem1));

    return result;
}
 
Share this answer
 
Comments
Kats2512 30-Aug-19 18:34pm    
just 8 years too late!
CHill60 2-Sep-19 4:43am    
Unexplained code dumps do not a solution make

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900