ListViews mit LVS_OWNERDATA - Was bewirkt dieser Style?
-
Zu jeder Reihe, die im ListView angezeigt werden soll, habe ich Informationen (Text und iIcon eines jeden Items) auf dem Heap gespeichert. In LVN_GETDISPINFO rufe ich diese Infos ab und lasse die Items anzeigen. Das klappt auch alles wunderbar, aber wenn ich den Style LVS_OWNERDATA hinzufüge, dann wird nichts mehr angezeigt. Ich habe bereits herausgefunden, dass das daran liegt, dass das Member lParam der LV_ITEM-Struktur, die mit LVN_GETDISPINFO mitgeliefert wird, auf NULL zeigt. Darin habe ich aber eigentlich meine Informationen gespeichert. Ohne LVS_OWNERDATA zeigt lParam aber auf meine Info-Struktur. Also meine Fragen:
1. Was bewirkt LVS_OWNERDATA eigentlich?
2. Warum ist das so?
3. Wie kann ich meine Items trotzdem anzeigen lassen?Vielleicht hilft auch etwas Code.
Meine Info-Struktur(en):struct ITEM_INFO { LPTSTR pszText; int iImage; BOOL ShowIcon; void Fill(LPCTSTR lpszText, int imageIndex, BOOL show_icon) { pszText = (LPTSTR)malloc(lstrlen(lpszText) + 1); lstrcpy(pszText, lpszText); iImage = imageIndex; ShowIcon = show_icon; } void DeleteText() { free(this->pszText); } }; //--------------------------------------------------------------------------- struct LINE_INFO { ITEM_INFO ItemInfos[5]; }; //--------------------------------------------------------------------------- struct TListViewInfo { TCHAR pszFileName[MAX_PATH]; TCHAR pszFolderName[MAX_PATH]; TCHAR pszSize[32]; TCHAR pszTypeName[256]; TCHAR pszDate[32]; int iFileIcon; };
So erstelle ich eine neue Zeile:
void __fastcall TForm1::LV_AddLine(TListViewInfo* lvInfo) { LV_ITEM lvi; LINE_INFO* pli; SHFILEINFO fi; // Den Icon-Index des Ordners herausfinden SHGetFileInfo(lvInfo->pszFolderName, 0, &fi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX); pli = new LINE_INFO; pli->ItemInfos[0].Fill(lvInfo->pszFileName , lvInfo->iFileIcon, TRUE); pli->ItemInfos[1].Fill(lvInfo->pszFolderName, fi.iIcon, TRUE); pli->ItemInfos[2].Fill(lvInfo->pszSize , 0, FALSE); pli->ItemInfos[3].Fill(lvInfo->pszTypeName , 0, FALSE); pli->ItemInfos[4].Fill(lvInfo->pszDate , 0, FALSE); lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE; lvi.state = 0; lvi.stateMask = 0; lvi.iItem = ListView_GetItemCount(hListView); lvi.iSubItem = 0; lvi.pszText = LPSTR_TEXTCALLBACK; lvi.lParam = (LPARAM)pli; lvi.iImage = I_IMAGECALLBACK; ListView_InsertItem(hListView, &lvi); }
In WM_NOTIFY behandle ich LVN_GETDISPINFO:
static LINE_INFO* plInfo; static LV_ITEM* plvi; static ITEM_INFO* pii; static NM_LISTVIEW* pnmlv; static LV_DISPINFO* pdi; . . . switch( ((LPNMHDR)lParam)->code ) { case LVN_GETDISPINFO: pdi = (LV_DISPINFO*)lParam; plvi = &pdi->item; if(plvi->mask & (LVIF_TEXT | LVIF_IMAGE)) { if( plvi->lParam ) // Hier ist &lParam == NULL, wenn LVS_OWNERDATA gesetzt { plInfo = (LINE_INFO*)(plvi->lParam);//LV_Items->Items[plvi->iItem]; pii = &plInfo->ItemInfos[plvi->iSubItem]; lstrcpy(plvi->pszText, pii->pszText); if(pii->ShowIcon) plvi->iImage = pii->iImage; } } break; . . .
-
Mit LVS_OWNERDATA speichert das control nur noch minimale Informaitonen über das Control (genauer gesagt: nur noch Focus und Selection - State). Du kannst die anzugebenden Informationen also nicht aus LPARAM ableiten, sondern aus iItem / iSubItem
Noch'n Tip: mit LVS_OWNERDATA kann man SetItem praktisch vergessen, um den State eines items zu ändern muß man LVS_SETITEMSTATE verwenden (hat mich zweiStunden gekostet
)
-
Vielen Dank für die Info. Ich glaub, ich lass das mit dem LVS_OWNERDATA doch lieber. Man hat mir anderweitig mitgeteilt, der Aufwand sei es nicht wert.
-
Kommt drauf an - hab' damit nen textviewer geschrieben, der ein 30MB Textfile in nullkommanix anzeigt....