排序 CMFCListCtrl 时的奇怪行为
Strange behaviour while sorting CMFCListCtrl
我扩展了 CMFCListCtrl
class 主要是为了能够轻松地按列排序。据我了解,实现 Sort
和 OnCompareItems
功能应该就足够了。
发生的情况是,排序对类型为 integer
的第 1 列工作正常,但对类型为 string
的第 2 列给出了奇怪的排序。没有错误,顺序已更改,但未按字母顺序排列。
int MyCMFCListCtrl::OnCompareItems(LPARAM lParam1, LPARAM lParam2, int iColumn)
{
if (iColumn == 0)
{
if (lParam1 > lParam2)
return -1;
else if (lParam1 < lParam2)
return 1;
else
return 0;
}
else if (iColumn == 1)
{
CString strCol1, strCol2;
strCol1 = GetItemText(lParam1, iColumn);
strCol2 = GetItemText(lParam2, iColumn);
return strCol1.Compare(strCol2);
}
return 0;
}
void MyCMFCListCtrl::Sort(int iColumn, BOOL bAscending, BOOL bAdd)
{
// Sort available for first and second column
if (iColumn > 1) return;
CMFCListCtrl::Sort(iColumn, bAscending, bAdd);
}
我在 OnCompareItems
中得到的值对两列都适用。但最终结果只对第一个有效。是否需要任何其他功能才能正常工作?
CMFCListCtrl::Sort
会调用 CListCtrl::SortItems
。 SortItems
会将 LPARAM
项目数据传递给回调函数。这个 LPARAM
是一个可以用 SetItemData
.
设置的值
即OnCompareItems
中的lParam1
和lParam2
,仅供参考LPARAM
数据
GetItemText(lParam1, iColumn)
在这种情况下是未定义的行为,因为 lParam1
不引用行号。
另请参阅 LVM_SORTITEMS
and LVM_SORTITEMSEX
的文档
您可以覆盖 Sort
并改为调用 SortItemsEx
。这样 lParam1
和 lParam2
将引用行号,而 GetItemText(lParam1, iColumn)
将是一个有效的调用,如下所示。请注意,仅当 SetItemData
较早调用时才使用 (iColumn == 0)
条件。
int MyCMFCListCtrl::OnCompareItems(LPARAM lParam1, LPARAM lParam2, int iColumn)
{
if(iColumn == 0)//assuming SetItemData was called earlier
return lParam1 - lParam2;
CString strCol1 = GetItemText(lParam1, iColumn);
CString strCol2 = GetItemText(lParam2, iColumn);
return strCol1.Compare(strCol2);
}
void MyCMFCListCtrl::Sort(int iColumn, BOOL bAscending, BOOL bAdd)
{
if(iColumn == 0)//assuming SetItemData was called earlier
{
//call SortItem and get LPARAM data in call back function
CMFCListCtrl::Sort(iColumn, bAscending, bAdd);
return;
}
//call SortItemEx instead, get row numbers in callback function
CWaitCursor wait;
GetHeaderCtrl().SetSortColumn(iColumn, bAscending, bAdd);
m_iSortedColumn = iColumn;
m_bAscending = bAscending;
SortItemsEx(CompareProc, (LPARAM)this);
}
我扩展了 CMFCListCtrl
class 主要是为了能够轻松地按列排序。据我了解,实现 Sort
和 OnCompareItems
功能应该就足够了。
发生的情况是,排序对类型为 integer
的第 1 列工作正常,但对类型为 string
的第 2 列给出了奇怪的排序。没有错误,顺序已更改,但未按字母顺序排列。
int MyCMFCListCtrl::OnCompareItems(LPARAM lParam1, LPARAM lParam2, int iColumn)
{
if (iColumn == 0)
{
if (lParam1 > lParam2)
return -1;
else if (lParam1 < lParam2)
return 1;
else
return 0;
}
else if (iColumn == 1)
{
CString strCol1, strCol2;
strCol1 = GetItemText(lParam1, iColumn);
strCol2 = GetItemText(lParam2, iColumn);
return strCol1.Compare(strCol2);
}
return 0;
}
void MyCMFCListCtrl::Sort(int iColumn, BOOL bAscending, BOOL bAdd)
{
// Sort available for first and second column
if (iColumn > 1) return;
CMFCListCtrl::Sort(iColumn, bAscending, bAdd);
}
我在 OnCompareItems
中得到的值对两列都适用。但最终结果只对第一个有效。是否需要任何其他功能才能正常工作?
CMFCListCtrl::Sort
会调用 CListCtrl::SortItems
。 SortItems
会将 LPARAM
项目数据传递给回调函数。这个 LPARAM
是一个可以用 SetItemData
.
即OnCompareItems
中的lParam1
和lParam2
,仅供参考LPARAM
数据
GetItemText(lParam1, iColumn)
在这种情况下是未定义的行为,因为 lParam1
不引用行号。
另请参阅 LVM_SORTITEMS
and LVM_SORTITEMSEX
您可以覆盖
Sort
并改为调用 SortItemsEx
。这样 lParam1
和 lParam2
将引用行号,而 GetItemText(lParam1, iColumn)
将是一个有效的调用,如下所示。请注意,仅当 SetItemData
较早调用时才使用 (iColumn == 0)
条件。
int MyCMFCListCtrl::OnCompareItems(LPARAM lParam1, LPARAM lParam2, int iColumn)
{
if(iColumn == 0)//assuming SetItemData was called earlier
return lParam1 - lParam2;
CString strCol1 = GetItemText(lParam1, iColumn);
CString strCol2 = GetItemText(lParam2, iColumn);
return strCol1.Compare(strCol2);
}
void MyCMFCListCtrl::Sort(int iColumn, BOOL bAscending, BOOL bAdd)
{
if(iColumn == 0)//assuming SetItemData was called earlier
{
//call SortItem and get LPARAM data in call back function
CMFCListCtrl::Sort(iColumn, bAscending, bAdd);
return;
}
//call SortItemEx instead, get row numbers in callback function
CWaitCursor wait;
GetHeaderCtrl().SetSortColumn(iColumn, bAscending, bAdd);
m_iSortedColumn = iColumn;
m_bAscending = bAscending;
SortItemsEx(CompareProc, (LPARAM)this);
}