如何用map数据结构实现C++ MFC虚拟列表控件?
MFC虚拟列表控件结合map显示数据问题解决
问题根源
你的代码里每次都把迭代器iter初始化为mapShip->begin(),没有根据列表行号nRow移动到对应的元素位置,所以所有行都重复显示map的第一条数据。另外case 4分支缺少break,会导致该列内容被case 5的内容覆盖。
修正方案
1. 正确定位map迭代器
std::map的迭代器是双向迭代器,可以用std::advance将迭代器移动到第nRow个元素的位置,完成行号到map元素的对应。
2. 修复switch分支的break缺失
给case 4添加break,避免逻辑串流导致列数据被覆盖。
修正后的完整代码
void AnchorDlg::OnGetdispinfoListctrl(NMHDR *pNMHDR, LRESULT *pResult) { NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR); LV_ITEM* pItem = &(pDispInfo)->item; CString str; if(pItem == NULL) return; int nRow = pItem->iItem; int nCol = pItem->iSubItem; if(nRow < 0 || nRow >= mapShip->size()) return; auto iter = mapShip->begin(); // 关键修改:将迭代器移动到对应行号的元素位置 std::advance(iter, nRow); if(pItem->pszText) { switch(nCol) { case 1: str.Format(_T("%.0f"), iter->second->mmsi); lstrcpy(pItem->pszText, str); break; case 2: str.Format(_T("%.7f"), iter->second->lat); lstrcpy(pItem->pszText, str); break; case 3: str.Format(_T("%.7f"), iter->second->lng); lstrcpy(pItem->pszText, str); break; case 4: str.Format(_T("%.1f"), iter->second->sog); lstrcpy(pItem->pszText, str); break; // 添加缺失的break case 5: str.Format(_T("%.1f"), iter->second->cog); lstrcpy(pItem->pszText, str); break; // 统一添加break避免后续分支出错 } } *pResult = 0; }
可选性能优化
std::advance在双向迭代器上是O(n)操作,1000条数据虽能运行,但可以提前将map元素存入vector做索引,把访问复杂度降到O(1):
// 对话框类添加成员变量:std::vector<YourShipType*> m_shipIndex; // 当mapShip数据更新时同步更新索引: m_shipIndex.clear(); for (auto& pair : *mapShip) { m_shipIndex.push_back(pair.second); } // 在OnGetdispinfoListctrl中直接使用索引: if(nRow < 0 || nRow >= m_shipIndex.size()) return; YourShipType* pShip = m_shipIndex[nRow]; // 后续switch分支直接用pShip替代iter->second即可
内容的提问来源于stack exchange,提问作者Hunni
相关产品推荐
相关产品推荐

