C++ ListView单条数据重复显示求助:如何循环加载std::vector数据
问题描述
我有6条公司数据需要显示在ListView控件中,手动添加列和子项的代码可正常运行:
添加列的代码:
LvCol.pszText = header1; //wchar_t header LvCol.cx = 0x80; LvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; SendMessage(ListCompanyInfoTable, LVM_INSERTCOLUMN, 0, (LPARAM)&LvCol);
添加子项的代码:
item.iSubItem = 0; SendMessageW(ListCompanyInfoTable, LVM_INSERTITEM, 0, (LPARAM)&item); item.mask = LVIF_TEXT; item.pszText = col1; item.cchTextMax = wcslen(item.pszText); SendMessageW(ListCompanyInfoTable, LVM_SETITEM, 0, (LPARAM)&item);
现在希望通过循环遍历存储公司数据的std::vector优化代码,但遇到问题:首次编写的循环代码中,第一行数据正常显示,后续行均重复第一行内容;修改后,iSubItem能正确读取所有项,但始终无法将下一家公司数据添加到下一行,重复显示第一家公司的数据。
补充相关代码:
数据定义与填充
std::vector<LPWSTR> Columns; std::vector<LPWSTR> TableData; std::vector<Company> companiesInGame; Company company1(L"American Gas Co", L"1930", L"ACG", 2000000, 500000); Company company2(L"TruGrocers", L"1940", L"TRG", 1525000, 300000); Company company3(L"Northern Airlines", L"1929", L"NAR", 1500000, 220000); Company company4(L"Jackson Estates", L"1938", L"JAE", 1970000, 255000); Company company5(L"High Point Hotels", L"1920", L"HPH", 970000, 250000); Company company6(L"Chucker's Truckers", L"1940", L"CHT", 600000, 100000); companiesInGame.push_back(company1); companiesInGame.push_back(company2); companiesInGame.push_back(company3); companiesInGame.push_back(company4); companiesInGame.push_back(company5); companiesInGame.push_back(company6); for (int i = 0; i < companiesInGame.size(); i++) { TableData.push_back(companiesInGame[i].CompanyNameBuffer); TableData.push_back(companiesInGame[i].CompanyCodeBuffer); TableData.push_back(companiesInGame[i].YearEstablishedBuffer); TableData.push_back(companiesInGame[i].TotalNetWorthBuffer); TableData.push_back(companiesInGame[i].TotalSharesBuffer); TableData.push_back(companiesInGame[i].PricePerShareBuffer); }
Company类构造函数
Company::Company(std::wstring CompanyName, std::wstring YearEstablished, std::wstring CompanyCode, double TotalNetWorth, int TotalShares) { this->companyName = CompanyName; this->yearEstablished = YearEstablished; this->iCompanyNetWorth = TotalNetWorth; this->iTotalShares = TotalShares; //Format character arrays for Printing CompanyName.copy(CompanyNameBuffer, 100); YearEstablished.copy(YearEstablishedBuffer, 100); CompanyCode.copy(CompanyCodeBuffer, 100); SetStockInfo(); size_t CompanyNameBufferLength = CompanyName.length(); CompanyNameBuffer[CompanyNameBufferLength] = '\0'; size_t YearEstablishedBufferLength = YearEstablished.length(); YearEstablishedBuffer[YearEstablishedBufferLength] = '\0'; size_t CompanyCodeBufferLength = CompanyCode.length(); CompanyCodeBuffer[CompanyCodeBufferLength] = '\0'; //Convert integer values to string for Printing swprintf_s(TotalNetWorthBuffer, 20, L"$ %lf", TotalNetWorth); swprintf_s(TotalSharesBuffer, 20, L"%d", TotalShares); swprintf_s(PricePerShareBuffer, 20, L"$ %.2lf", this->iPricePerShare); }
修复方案
核心问题分析
LVM_INSERTITEM参数错误:原代码中每次调用SendMessageW插入行时,第二个参数传了0,这会把所有新行都插入到索引0的位置,导致后续行覆盖前一行,最终所有数据都显示在第一行。正确做法是传入当前行索引x,或者传-1让控件自动追加到末尾。- TableData索引计算错误:原循环中直接用
y获取TableData[y],只会拿到第一家公司的列数据。需要用x * numColumns + y来定位当前行对应的列数据。 - 内层循环范围错误:原代码中内层循环遍历总单元格数
numTableCells,这会导致单行道重复设置所有单元格数据,应该只遍历单行道的列数numColumns。
修复后的循环代码
size_t numColumns = Columns.size(); size_t numRows = companiesInGame.size(); LVITEM tableCell = { 0 }; memset(&tableCell, 0, sizeof(tableCell)); tableCell.mask = LVIF_TEXT; // 提前设置mask,避免重复赋值 for (int x = 0; x < numRows; x++) { // 插入新行,第二个参数传x指定行索引,或者传-1自动追加 tableCell.iItem = x; tableCell.iSubItem = 0; // 设置第一列的文本(对应CompanyName) tableCell.pszText = TableData[x * numColumns + 0]; tableCell.cchTextMax = (int)wcslen(tableCell.pszText); SendMessageW(ListCompanyInfoTable, LVM_INSERTITEM, x, (LPARAM)&tableCell); // 设置当前行的剩余列 for (int y = 1; y < numColumns; y++) { tableCell.iSubItem = y; tableCell.pszText = TableData[x * numColumns + y]; tableCell.cchTextMax = (int)wcslen(tableCell.pszText); // LVM_SETITEM的第二个参数传x指定要修改的行 SendMessageW(ListCompanyInfoTable, LVM_SETITEM, x, (LPARAM)&tableCell); } }
进一步优化建议
可以跳过TableData这个中间载体,直接遍历companiesInGame取数据,避免索引计算错误,代码更直观:
size_t numColumns = Columns.size(); size_t numRows = companiesInGame.size(); LVITEM tableCell = { 0 }; memset(&tableCell, 0, sizeof(tableCell)); tableCell.mask = LVIF_TEXT; for (int x = 0; x < numRows; x++) { Company& currCompany = companiesInGame[x]; tableCell.iItem = x; // 插入行并设置第一列 tableCell.iSubItem = 0; tableCell.pszText = currCompany.CompanyNameBuffer; tableCell.cchTextMax = (int)wcslen(tableCell.pszText); SendMessageW(ListCompanyInfoTable, LVM_INSERTITEM, x, (LPARAM)&tableCell); // 设置剩余列 tableCell.iSubItem = 1; tableCell.pszText = currCompany.CompanyCodeBuffer; tableCell.cchTextMax = (int)wcslen(tableCell.pszText); SendMessageW(ListCompanyInfoTable, LVM_SETITEM, x, (LPARAM)&tableCell); tableCell.iSubItem = 2; tableCell.pszText = currCompany.YearEstablishedBuffer; tableCell.cchTextMax = (int)wcslen(tableCell.pszText); SendMessageW(ListCompanyInfoTable, LVM_SETITEM, x, (LPARAM)&tableCell); tableCell.iSubItem = 3; tableCell.pszText = currCompany.TotalNetWorthBuffer; tableCell.cchTextMax = (int)wcslen(tableCell.pszText); SendMessageW(ListCompanyInfoTable, LVM_SETITEM, x, (LPARAM)&tableCell); tableCell.iSubItem = 4; tableCell.pszText = currCompany.TotalSharesBuffer; tableCell.cchTextMax = (int)wcslen(tableCell.pszText); SendMessageW(ListCompanyInfoTable, LVM_SETITEM, x, (LPARAM)&tableCell); tableCell.iSubItem = 5; tableCell.pszText = currCompany.PricePerShareBuffer; tableCell.cchTextMax = (int)wcslen(tableCell.pszText); SendMessageW(ListCompanyInfoTable, LVM_SETITEM, x, (LPARAM)&tableCell); }
内容的提问来源于stack exchange,提问作者DaBigBoy
相关产品推荐
相关产品推荐

