在排序CMFCListCtrl时出现奇怪的行为

3

我扩展了 CMFCListCtrl 类,主要是为了能够轻松按列排序。根据我的经验,只需实现 SortOnCompareItems 函数即可。

然而,当第二列的类型为string时,发生了奇怪的排序问题。没有错误提示,但是排序结果不是按字母表顺序排列。


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 中的值对于两个列都是正确的。但最终结果仅对第一个列有效。是否还需要其他函数才能使其正常工作?


“但它给出了无效的排序”:这是什么意思?是否有错误消息?程序是否崩溃?这是ASSERT吗?请编辑您的问题并更具体地描述。 - Jabberwocky
还要检查strCol1strCol2是否实际包含正确的字符串。在return strCol1.Compare(strCol2);之前加入TRACE("OnCompareItems: %s %s\n", strCol1, strCol2);,并检查调试输出。 - Jabberwocky
1
这需要其他功能吗?-- 我们不知道您实际的数据是什么。因此,现在我们无法假设排序是“不工作”的。 - PaulMcKenzie
还有,这是什么意思:“which type is test.”? - Jabberwocky
1
是否可以直接使用 https://learn.microsoft.com/en-us/cpp/mfc/reference/cmfclistctrl-class?view=vs-2019#setsortcolumn (SetSortColumn) 函数? - Andrew Truckle
1
这个回答解决了你的问题吗?ClistCtrl列的排序不正确 - Andrew Truckle
1个回答

4

CMFCListCtrl::Sort将调用CListCtrl::SortItemsSortItems将向回调函数传递LPARAM项数据。这个LPARAM是一个可以用SetItemData设置的值。

这意味着OnCompareItems中的lParam1lParam2仅涉及LPARAM数据。

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

另请参阅LVM_SORTITEMSLVM_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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接