I have a question while studying C MFC.
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();
if(pItem->pszText)
{
switch(nCol)
{
case 1:
str.Format(_T("%.0f"), iter->second->mmsi);
//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);
case 5:
str.Format(_T("%.1f"), iter->second->cog);
lstrcpy(pItem->pszText, str);
}
}
*pResult = 0;
}
mapShip
consists of double and data objects.
I want to print out 1000 data, but only one data is printed.
I've used iter but only one data is output. Same data print repeat.
I must used map data structure.
I don't know how to use the map.
CodePudding user response:
You don't seem to do anything with pItem->iItem
(nRow
), you just set it to the beginning of the list. You should instead search your data with this - requests may arrive in any random order. You don't have to iterate the list in OnGetdispinfoListctrl()
, instead you should return the data to be displayed, given the iItem
and iSubItem
members. So consider using a more efficient structure to hold your data, if they are really too many (lists are not, because they are serial access structures, not random access ones). Also, don't copy the text into Item.pszText
, instead set Item.pszText
to point to your data. The if(pItem->pszText)
check is not needed, neither is correct:
void AnchorDlg::OnGetdispinfoListctrl(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
LV_ITEM* pItem = &(pDispInfo)->item;
// Persistent Buffer
static 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();
auto iter = SearchMyData(nRow);
switch (nCol)
{
case 1:
str.Format(_T("%.0f"), iter->second->mmsi);
pItem->pszText = str;
break;
case 2:
str.Format(_T("%.7f"), iter->second->lat);
pItem->pszText = str;
break;
case 3:
str.Format(_T("%.7f"), iter->second->lng);
pItem->pszText = str;
break;
case 4:
str.Format(_T("%.1f"), iter->second->sog);
pItem->pszText = str;
break;
case 5:
str.Format(_T("%.1f"), iter->second->cog);
lstrcpy(pItem->pszText, str);
}
*pResult = 0;
}
CodePudding user response:
A virtual list-view control is a list-view control that doesn't store any data. Instead, users just tell the control how many items there are (by sending a LVM_SETITEMCOUNT
message), and the control implementation will subsequently call back to the user to provide the data for the individual cells (by way of the LVN_GETDISPINFO
message).
While the code in question is responding to the LVN_GETDISPINFO
message, evaluating the nRow
(and nCol
) identifying the cell to be displayed, it doesn't use that data for information lookup. The code perpetually accesses the first item (mapShip->begin()
) for display. However, it should be using nRow
to index into the data represented by mapShip
(see How to Use Virtual List-View Controls for an example).
Assuming that mapShip
is an instantiation of the std::map
class template, you'll want to index into that map using nRow
as the index, e.g.:
auto const& value = mapShip[nRow];
and use value
in place of iter
. This will display items in the order they are stored in the associative container (sorted by key). If you need a different ordering, you'll have to map nRow
onto the respective index in the map.