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....


Anmelden zum Antworten