CListCtrl & sort icons


I have a CListCtrl in a CDialog on which I capture the ON_NOTIFY message LVN_COLUMNCLICK, and then depending upon whether we're doing an ascending or descending sort I set the sort icon. This is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	
	const int nSortCol = pNMLV->iSubItem;
	static int nPrevSortCol(-1);
	static bool ascending(true);
	
	CHeaderCtrl* pHDR = m_metadatalist.GetHeaderCtrl();
	HDITEM headerInfo;

	if (nPrevSortCol == nSortCol)
	{
		ascending = !ascending;
	}
	else
	{
		if (nPrevSortCol != -1 && pHDR->GetItem(nPrevSortCol, &headerInfo))
		{
			headerInfo.fmt = 0x4000;
			pHDR->SetItem(nPrevSortCol, &headerInfo);
		}

		nPrevSortCol = nSortCol;
		ascending = true;
	}

	if (pHDR->GetItem(nSortCol, &headerInfo))
	{
		if (ascending)
		{
			headerInfo.fmt |= HDF_SORTUP;
			headerInfo.fmt &= ~HDF_SORTDOWN;
		}
		else
		{
			headerInfo.fmt |= HDF_SORTDOWN;
			headerInfo.fmt &= ~HDF_SORTUP;
		}

		pHDR->SetItem(nSortCol, &headerInfo);
	}

	std::sort(m_vMetadata.begin(), m_vMetadata.end(), CSortData(nSortCol, ascending));
	m_metadatalist.Invalidate();

	*pResult = 0;


The sort icon (either up or down) is correctly set in debug mode but is strangly absent in release mode. In release mode the code is executed but no icon is showing in the header of the column clicked on. Anyone any ideas why not?
It's your sort callback that determines the sort order, you shouldn't need to do anything on a notify handler.

BTW, what notification are you hanging this code off?

Here is where this code resides:

1
2
3
4
BEGIN_MESSAGE_MAP(CXbrlMetadataExtractorDlg, CDialog)
	...
	ON_NOTIFY(LVN_COLUMNCLICK, IDC_METADATA, &CXbrlMetadataExtractorDlg::OnLvnColumnclickMetadata)
END_MESSAGE_MAP()


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
void CXbrlMetadataExtractorDlg::OnLvnColumnclickMetadata(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	
	const int nSortCol = pNMLV->iSubItem;
	static int nPrevSortCol(-1);
	static bool ascending(true);
	
	CHeaderCtrl* pHDR = m_metadatalist.GetHeaderCtrl();
	HDITEM headerInfo;

	if (nPrevSortCol == nSortCol)
	{
		ascending = !ascending;
	}
	else
	{
		if (nPrevSortCol != -1 && pHDR->GetItem(nPrevSortCol, &headerInfo))
		{
			headerInfo.fmt = 0x4000;
			pHDR->SetItem(nPrevSortCol, &headerInfo);
		}

		nPrevSortCol = nSortCol;
		ascending = true;
	}

	if (pHDR->GetItem(nSortCol, &headerInfo))
	{
		if (ascending)
		{
			headerInfo.fmt |= HDF_SORTUP;
			headerInfo.fmt &= ~HDF_SORTDOWN;
		}
		else
		{
			headerInfo.fmt |= HDF_SORTDOWN;
			headerInfo.fmt &= ~HDF_SORTUP;
		}

		pHDR->SetItem(nSortCol, &headerInfo);
	}

	std::sort(m_vMetadata.begin(), m_vMetadata.end(), CSortData(nSortCol, ascending));
	m_metadatalist.Invalidate();

	*pResult = 0;
}



I' using ComCtl32.dll version 6 by putting the following in the stdafx.cpp:

1
2
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

I have Owner Data set to true on as I populate the List CTRL via the message LVN_GETDISPINFO.

If I then use the CMFCListCtrl rather than the CListCtrl, when I go to sort the data I get an assertion in the CListCtrl::SortItems called from CMFCListCtrl::Sort() which passed the CMFCListCtrl::CompareProc

Any idea how I can get this to work?

I have decided to write a small CMFCListCtrl extension class that overrides the Sort function in which I then send a windows registered message which I then deal with in my dialog:

1
2
3
4
5
6
7
8
9
10
11
12
void CMFCListCtrlEx::Sort(int iColumn, BOOL bAscending /*= TRUE*/, BOOL bAdd /*= FALSE*/)
{
	CWaitCursor wait;

	GetHeaderCtrl().SetSortColumn(iColumn, bAscending, bAdd);

	m_iSortedColumn = iColumn;
	m_bAscending = bAscending;

	CWnd* pParent = GetParent();
	::SendMessage(pParent->GetSafeHwnd(), WRM_LV_SORT, iColumn, bAscending);
}


1
2
3
4
5
6
7
8
LRESULT CXbrlMetadataExtractorDlg::OnLvSortMetadata(WPARAM wParam, LPARAM lParam)
{
	bool ascending = lParam != 0;
	std::sort(m_vMetadata.begin(), m_vMetadata.end(), CSortData(wParam, ascending));
	m_metadatalist.Invalidate();

	return 0;
}


Works fine now.
Registered users can post here. Sign in or register to post.