排序 CMFCListCtrl 时的奇怪行为

Strange behaviour while sorting CMFCListCtrl

我扩展了 CMFCListCtrl class 主要是为了能够轻松地按列排序。据我了解,实现 SortOnCompareItems 功能应该就足够了。

发生的情况是,排序对类型为 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::SortItemsSortItems 会将 LPARAM 项目数据传递给回调函数。这个 LPARAM 是一个可以用 SetItemData.

设置的值

OnCompareItems中的lParam1lParam2,仅供参考LPARAM数据

GetItemText(lParam1, iColumn) 在这种情况下是未定义的行为,因为 lParam1 不引用行号。

另请参阅 LVM_SORTITEMS and LVM_SORTITEMSEX

的文档


您可以覆盖 Sort 并改为调用 SortItemsEx。这样 lParam1lParam2 将引用行号,而 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);
}