为CListCtrl用sortitems来排序时,大于等于二列的列表排序都正常,只有一列的列表排序不正确。
下面是回调函数CompareFunc的一段代码。
LVFINDINFO fi1;
memset(&fi1, 0, sizeof(fi1));
fi1.flags = LVFI_PARAM;
fi1.lParam = lParam1;
LVFINDINFO fi2;
memset(&fi2, 0, sizeof(fi2));
fi2.flags = LVFI_PARAM;
fi2.lParam = lParam2; int iIndex1 = pInvDtlList->FindItem(&fi1);
int iIndex2 = pInvDtlList->FindItem(&fi2);用TRACE时,发现用lParam去找索引,居然找不到,索引为-1,lPARAM在正常范围内,也就是说item data的绑定出现了混乱。
在网上到处查也没有发现这个问题有人提过,觉得很奇怪,希望各位赐教。
下面是回调函数CompareFunc的一段代码。
LVFINDINFO fi1;
memset(&fi1, 0, sizeof(fi1));
fi1.flags = LVFI_PARAM;
fi1.lParam = lParam1;
LVFINDINFO fi2;
memset(&fi2, 0, sizeof(fi2));
fi2.flags = LVFI_PARAM;
fi2.lParam = lParam2; int iIndex1 = pInvDtlList->FindItem(&fi1);
int iIndex2 = pInvDtlList->FindItem(&fi2);用TRACE时,发现用lParam去找索引,居然找不到,索引为-1,lPARAM在正常范围内,也就是说item data的绑定出现了混乱。
在网上到处查也没有发现这个问题有人提过,觉得很奇怪,希望各位赐教。
void CInvItemDetailListCtrl::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// TODO: ここにコントロール通知ハンドラ コードを追加します。
if (m_bSorted != TRUE)
{
return;
}
//並べ替えるために必要な処理
int iCount = GetItemCount();
for (int i = 0; i < iCount; i++)
{
SetItemData(i, i);
} m_iCurCol = (int)pNMLV->iSubItem; SortItems((PFNLVCOMPARE)CompareFunc, (DWORD_PTR)this);
m_bSortAscending = !m_bSortAscending;
*pResult = 0;
}
TRACE(_T("%s (lParam1:%d;index1:%d) == %s (lParam2:%d;index2:%d) | 0\n"), strItem1, lParam1, iIndex1, strItem2, lParam2, iIndex2);Output:
(lParam1:65;index1:-1) < 2007 Microsoft Office Suite Service Pack 1 (SP1) (lParam2:117;index2:72) | -1
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// TODO: ここにコントロール通知ハンドラ コードを追加します。
if (m_bSorted != TRUE)
{
return;
}
//並べ替えるために必要な処理
int iCount = GetItemCount();
for (int i = 0; i < iCount; i++)
{
SetItemData(i, i);
} m_iCurCol = (int)pNMLV->iSubItem; SortItems((PFNLVCOMPARE)CompareFunc, (DWORD_PTR)this);
m_bSortAscending = !m_bSortAscending;
*pResult = 0;
}int CALLBACK CInvItemDetailListCtrl::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
CInvItemDetailListCtrl* pInvDtlList = (CInvItemDetailListCtrl*) lParamSort; CString strItem1 = pInvDtlList->GetItemText((int)lParam1, pInvDtlList->m_iCurCol);
CString strItem2 = pInvDtlList->GetItemText((int)lParam2, pInvDtlList->m_iCurCol);
if (pInvDtlList->m_bSortAscending == TRUE)
{
return strItem1 < strItem2;
}
else
{
return strItem1 > strItem2;
}
}
{
//全部にアイテムと列を削除する
DeleteAllItems();
while(DeleteColumn(0));
int i;
switch (m_iInvItemIndex)
{
case ……:
……;
break;
case INV_REGISTRY_IMAGE:
//----------------------------------------------------
//レジストリ検索結果情報
//----------------------------------------------------
InsertColumn(0, INV_RGRST_SOFT_N, LVCFMT_LEFT, SINGLE_COLUMN_WIDTH, 0);
LoadColumnInfo(COLUMN_NAME13, 1); for(i = 0; i < pInvInfo->m_InvRegClntInfoArray.GetCount(); i++)
{
InsertItem(0, pInvInfo->m_InvRegClntInfoArray.ElementAt(i).szSoftware);
}
m_bSorted = TRUE;
//並べ替えるために必要な処理
{
int iCount = GetItemCount();
for (i = 0; i < iCount; i++)
{
SetItemData(i, (DWORD)pInvInfo->m_InvRegClntInfoArray.ElementAt(i).szSoftware);
} m_iCurCol = 0;
SortItems(CompareFunc, (DWORD_PTR)this);
m_bSortAscending = FALSE;
}
break;
一种就是把一列变两列,再插入一列,排序就正常了。
另一种是将item的字符串和item绑定,排序也正常了。
{
CInvItemDetailListCtrl* pInvDtlList = (CInvItemDetailListCtrl*) lParamSort; CString strItem1 = pInvDtlList->GetItemText((int)lParam1, pInvDtlList->m_iCurCol);
CString strItem2 = pInvDtlList->GetItemText((int)lParam2, pInvDtlList->m_iCurCol);
if (pInvDtlList->m_bSortAscending == TRUE)
{
return strItem1.Compare(strItem2);
}
else
{
return strItem2.Compare(strItem1);
}
}
因为一开始就要将数据排序,所以在插入之后还调用了SortItems。
另外
m_bSortAscending = !m_bSortAscending;
应该加在排序之前,并判断此次点击的列号与上次相同时执行。
排序调用Qsort 绝对没有说哪行哪列不能排的。
而且虚拟列表控件那个速度~爽