对CMFCLISTCTRL排序时奇怪的(?)行为
Strange (?) behaviour while sorting CMFCListCtrl
我有一个支持排序的cmfclistctrl的子类,读取我必须实现的文档虚拟方法:
virtual int OnCompareItems(LPARAM lParam1, LPARAM lParam2, int nColumn);
其中lparam1和lparam2是某种参数,在创建列表控件时指定。
由于我需要按字母顺序排列的,因此我以这种方式插入了我的行:
item.mask = LVIF_COLFMT | LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;
for (nI = 0; nI ....)
{
// UMASK, ITEM IDX, TEXT, STATE 1, STATE 2, IMAGE IDX, LPARAM
m_lstMateriali.InsertItem(item.mask, nI, _T(" "), 0, 0, SelezionaIcona(itIM->m_bSelez, itIM->m_eStatus), nI);
strQnt.Format(_T("%d"), itIM->m_nIdBolla);
m_lstMateriali.SetItemText(nI, 1, strQnt);
m_lstMateriali.SetItemText(nI, 2, itIM->m_strCodMater);
m_lstMateriali.SetItemText(nI, 3, itIM->m_strDescrMater);
m_lstMateriali.SetItemText(nI, 4, itIM->m_strColore);
strQnt.Format(_T("%d"), itIM->m_nDaTag);
m_lstMateriali.SetItemText(nI, 5, strQnt);
m_lstMateriali.SetItemData(nI, nI);
}
此时,我的子类分类方法:
virtual int OnCompareItems(LPARAM lParam1, LPARAM lParam2, int nColumn)
{
int nCol_1; ///<
int nCol_2; ///<
CString strCol_1; ///<
CString strCol_2; ///<
strCol_1 = GetItemText(lParam1, nColumn);
strCol_2 = GetItemText(lParam2, nColumn);
switch (nColumn)
{
case 2:
return strCol_1.Compare(strCol_2);
}
}
效果很大。但是现在,由于排序,我的lparams不再正确,因为它们代表了行号。然后,我处理了标头单击通知,这发生在之后发生的:
void CEliCUTK2SceltaMaterialiDlg::OnHdnItemclickLstSmListapezzi(NMHDR * pNMHDR, LRESULT * pResult)
{
int nNumRig;
CString strCodMat;
LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
LVITEM item;
nNumRig = m_lstMateriali.GetItemCount();
memset(&item, 0, sizeof(LVITEM));
item.mask = LVIF_PARAM;
for (int nI = 0; nI < nNumRig; nI++)
{
item.iItem = nI;
item.lParam = nI;
m_lstMateriali.SetItem(&item); // (1)
strCodMat = m_lstMateriali.GetItemText(nI, 2);
// bla bla about item data
}
*pResult = 0;
}
这可能是最糟糕的做法,但就目前而言,它很好:我将新的lparams设置为新的行号。我还在第(1)点之前和之后拾取了文字,以检查我是否更新了行,一切似乎都很好:我先获得了旧的param和新的param。
现在是什么:我在行标题中再次单击了排序降序以及得到什么?一切都很混乱。我决定检查一些内容,然后添加了以下代码:
void CEliCUTK2SceltaMaterialiDlg::OnLvnItemchangedLstSmListapezzi(NMHDR * pNMHDR, LRESULT * pResult)
{
int nSot, nTip;
CString strID;
DWORD_PTR dwID;
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
LVITEM item;
if (pNMLV->uNewState == 3)
{
dwID = m_lstMateriali.GetItemData(pNMLV->iItem);
memset(&item, 0, sizeof(LVITEM));
item.mask = LVIF_PARAM;
item.iItem = pNMLV->iItem;
m_lstMateriali.GetItem(&item);
strID.Format(_T("PARAM: %ld."), item.lParam);
AfxMessageBox(strID);
}
*pResult = 0;
}
重新启动程序,再次对列表进行排序,然后单击 first row(在再次检查新的LPARAMS之后正确)我收到了消息:
PARAM: 10.
我应该得到:
PARAM: 0.
10是旧位置。我在某个地方有一些东西吗?
通常,您要在lparam中存储的东西可以使您可以回到用来填充列表的数据,或者是包含包含的结构的指针比较的数据。如果您有一个并行的Clist或STD :: List Collection(或Carray或STD :: vector),则将索引起作用,该索引在ClistCtrl的一生中不会更改其订单。
在进行分类或插入过程中,列表中的项目10在您的示例中可能具有2个。您想使用" 2"将原始数据源(Clist,Carray,记录集或其他内容)索引,然后在此处获取数据并在原始数据上使用您的比较。因为,当您排序时,LPARAM中的索引将与ClistCtrl(或CMFClistCtrl)中的索引相同。
您可以分配比较所需的所有数据的结构,并将其存储在LPARAM成员中。(在某些MFC类中,您使用setItemDataptr)。要清理数据,请处理lvn_deleteitem消息。
解决问题:它在
中// bla bla about item data
在哪里更新数据的位置:
SetItemData(int, DWORD_PTR);
根据https://msdn.microsoft.com/it-it/library/936147y4.4.4.4.aspx ItemData实际上是LVITEM结构中指定的LPARAM值。
- 理解boost::asio-async_read在无需读取内容时的行为
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- arr[-1]在c++中的奇怪行为
- 继承期间显示未知行为的子类
- 如何在c++中使用引用实现类似python的行为
- G锁定铸造到基础上会释放模拟行为
- 在C++中对T*类型执行std::move的意外行为
- std::当在256字节边界上写入整数时,流的奇怪行为
- 不知道某个东西是否被忽略会引入未定义的行为吗
- 奇怪的构造函数行为
- 重载运算符new[]的行为取决于析构函数
- 不同语言中相同代码的不同行为
- 处理除以零会导致<csignal>意外行为
- 试图理解类对象的行为
- c++11评估顺序(未定义的行为)
- 从结构寻址时,MMAP变量的行为很奇怪
- 我可以做些什么来消除或最小化这种将提供相同功能和行为的代码重复
- 读取文件时运行时的未知行为
- 排序CMFCListCtrl时出现奇怪行为
- 对CMFCLISTCTRL排序时奇怪的(?)行为