ImageList in list control



  • Heiho

    Ich hab da mal ne frage, und zwar hab ich hier schon meine List Control klasse wo ich alle moeglichen funktionen gekapselt habe

    was ich jetzt suche ist die moeglichkeit die selben icons anzeigen zu lassen wie in windows
    also ich lese einen ordner aus und lasse alle gefundenen dateien anzeigen
    diese sollen alle nu auch die selben icons bekommen wie im explorer

    wie kann ich das bewerkstelligen?


  • Mod

    Dies ist abhängig von der Extension. Die Funktion SHGetFileInfo mit SHGFI_ICON liefert Dir das Icon. Einfach mit Add an eine ImamgeList anhängen und das wars.

    Aber Achtung bitte darauf achten, dass die Icons auch wieder freigegeben werden müssen!
    SHGFI_SYSICONINDEX kann man evtl. auch verwenden!



  • irgendwas mach ich falsch- ich hab keine ahnung wie ich ueberhaupt irgendein icon anzeigen lassen kann

    .
    .
    .
    LVITEM item;
    item.mask = LVIF_COLUMNS|LVIF_TEXT|LVIF_IMAGE;
    item.iSubItem = 0;
    item.cColumns = 0;
    item.iItem = uiPos;
    item.pszText = str;
    
    SHFILEINFO shfi;
    HIMAGELIST hSysImgList;
    
    hSysImgList = (HIMAGELIST)SHGetFileInfo(_T("C:\\FilterLog.log"), 0, &shfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX);
    item.iImage = shfi.iIcon;
    .
    .
    .
    

    //ist zusammen gegooglet

    ich bekomm zwar in shfi.iIcon den richtigen icon index, aber das aendert nichts

    so ist die list erstellt:

    m_Handle = ::CreateWindow(WC_LISTVIEW, _T(""), WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT|LVS_EDITLABELS, ...);
    ::SendMessage(m_Handle, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT|LVS_SMALLICON);
    


  • habs hinbekommen

    LVITEM item;
    item.mask = LVIF_COLUMNS|LVIF_TEXT|LVIF_IMAGE;
    item.iSubItem = 0;
    item.cColumns = 0;
    item.iItem = uiPos;
    item.pszText = str;
    
    SHFILEINFO shfi;
    HIMAGELIST hSysImgList;
    hSysImgList = ImageList_Create(16, 16, ILC_MASK, 1, 0);
    //file for testing
    SHGetFileInfo(_T("C:\\FilterLog.log"), 0, &shfi, sizeof(SHFILEINFO), SHGFI_ICON);
    int erg = ImageList_AddIcon(hSysImgList, shfi.hIcon);
    
    ::SendMessage(m_Handle, LVM_SETIMAGELIST, LVSIL_SMALL, reinterpret_cast<LPARAM>(static_cast<HIMAGELIST>(hSysImgList)));
    item.iImage = 0;
    


  • hmm

    doch nicht so recht, ich hab sobald ich es teste alle items mit den selben icon /=


  • Mod

    Du musst natürlich die Icons sammeln. Dann bekommst Du für jedes Icon das Du in die Imagelist einsetzt eine ID. Diese ID musst Du bei dem List Item wieder angeben. Wenn Du immer Imagelist Index 0 angibst bekomst Du immer nur das erste Icon!



  • auf den trichter des sammelns bin ich auch schon gekommen, ich habe

    HIMAGELIST hSysImgList;
    

    jetzt in der klasse damit die immer gueltig ist

    dann beim adden eines elements mach ich immer

    SHFILEINFO shfi;
    hSysImgList = ImageList_Create(16, 16, ILC_MASK, 200, 200);
    
    _tstring path = strPath;
    path += strName;
    
    SHGetFileInfo(path.c_str(), 0, &shfi, sizeof(SHFILEINFO), SHGFI_ICON);
    ImageList_AddIcon(hSysImgList, shfi.hIcon);
    ::SendMessage(m_Handle, LVM_SETIMAGELIST, LVSIL_SMALL, reinterpret_cast<LPARAM>(static_cast<HIMAGELIST>(hSysImgList)));
    item.iImage = shfi.iIcon; // hier probier ich rum
    

    ich dacht shfi.iIcon waere die ID - aber ich bekomm nu nie icons angezeigt
    was mach ich falsch - google hilft mir kein stueck - such schon stundenlang


  • Mod

    ImageList_AddIcon returninert einen Index!
    Diese gibt den Index des Bildes an. So schwer ist das mit den Imagelists doch wirklich nicht. Wie hast Du den vorher ImageLists verwendet?



  • vorher ? noch nie - ist das erste mal das ich damit in beruehrung komm #gg

    habs geschafft - das eine mit den add icon war noch der stolperstein

    was habe ich nu:

    Klasse

    HIMAGELIST hSysImgList;
    

    Konstruktor

    hSysImgList = ImageList_Create(16, 16, ILC_MASK, 200, 200);
    

    Nach dem Create

    ::SendMessage(m_Handle, LVM_SETIMAGELIST, LVSIL_SMALL, reinterpret_cast<LPARAM>(static_cast<HIMAGELIST>(hSysImgList)));
    

    beim adden

    SHFILEINFO shfi;
    _tstring path = strPath+strName;
    SHGetFileInfo(path.c_str(), 0, &shfi, sizeof(SHFILEINFO), SHGFI_ICON);
    int id = ImageList_AddIcon(hSysImgList, shfi.hIcon);
    item.iImage = id;
    

    eine kleine frage noch
    bei
    "hSysImgList = ImageList_Create(16, 16, ILC_MASK, 200, 200);"
    hab ich beides als 200 angegeben - gibt es da ein richtwert - wieviel sinnvoll/notwndig ist ?

    vielen dank {=


  • Mod

    1. Du solltest Dir ein internen mao aufbauen, sodaß Du extensions nur einmal lädst. Dann wird die Imagelist nicht endlos groß
    2. Wie groß Du die Imagelist machst hängt davon ab was Du reinpacken willst. Sind die Werte zu klein muss zu oft reallokiert werden. Sind die Werte zu groß verschwendest Du immens Speicher.



  • ist mir gestern auch noch in den sinn gekommen das ich irgendwie duplicates loeschenlassen sollte - muss ich erstmal schauen wie das funktioniert, da ich wie gesagt das erste mal damit in beruehung komm

    im speicher landen nur die small icons
    was ich mich grad aber frag, ich habe ja den wert fest eingegeben - du sagtest "muss zu oft reallokiert werden"
    macht die imagelist das dynamisch ?


  • Mod

    Du musst nichts doppeltes löschen, Du musst nur nachsehen ob Du das Icon schon hast für die entsprechende Dateiendung!

    Ja Imagelist vergrößert sich selbst den Speicherbereich. Lies doch die Doku, die entsprechenden zwei letzten Parameter geben das doch an.

    nInitial
    Number of images that the image list initially contains.
    nGrow
    Number of images by which the image list can grow when the system needs to resize the list to make room for new images. This parameter represents the number of new images the resized image list can contain.



  • Martin Richter schrieb:

    Du musst nichts doppeltes löschen, Du musst nur nachsehen ob Du das Icon schon hast für die entsprechende Dateiendung!

    da bin ich bisher am rumprobieren, ich pack das nicht

    mein problem ist - wie finde ich ein icon in der imagelist

    also ich hole das icon der datei

    int GetIconID(_tstring strFile){
        SHFILEINFO shfi;
        SHGetFileInfo(strFile.c_str(), 0, &shfi, sizeof(SHFILEINFO), SHGFI_ICON);
        return ImageList_AddIcon(hSysImgList, shfi.hIcon);
    }
    

    dann adde ich das und returniere den index

    aber ich brauch noch sowas (pseudocode)

    int GetIconID(_tstring strFile){
        SHFILEINFO shfi;
        SHGetFileInfo(strFile.c_str(), 0, &shfi, sizeof(SHFILEINFO), SHGFI_ICON);
        //---------------- Begin Pseudo
        int pos = ImageList_FindIcon(shfi.hIcon);
        if(pos >= 0)
            return pos;
        else
            return ImageList_AddIcon(hSysImgList, shfi.hIcon);
    }
    

    dazuedit:
    das hab ich eben gebastelt:

    int CListsControl::GetIconID(_tstring strFile){
    	SHFILEINFO shfi;
    	SHGetFileInfo(strFile.c_str(), 0, &shfi, sizeof(SHFILEINFO), SHGFI_ICON);
    	//return ImageList_AddIcon(hSysImgList, shfi.hIcon);
    	for(int i=0; i<ImageList_GetImageCount(hSysImgList); ++i){
    		HICON icon = ImageList_GetIcon(hSysImgList, i, ILD_MASK);
    		if(icon == shfi.hIcon)
    			return i;
    	}
    	return ImageList_AddIcon(hSysImgList, shfi.hIcon);
    }
    

    ist das richtig ? ich kann ganz schlecht ueberprüfen obs funktioniert



  • funktioniert anscheinend doch nicht /=

    das problem ist das ich die HICONs nicht vergleichen kann
    und wenn ich es probeweise adde und dann vergleiche aendert das auch nichts

    also lautet die frage - woher weiss ich ob ich das icon image bereits abgespeichert habe oder nicht
    muss ich nebenher eine map laufen lassen wo ich ext-string + id separat abspeicher?


  • Mod

    Habe ich das nicht geschrieben?
    Doch!

    Du solltest genau das tun! Eine map führen in der Du Extension und den vergebenen Index abspeicherst. PathFindExtension hilft Dir dabei. Achte darauf das die map Groß- und Kleinschreibung nicht unterscheidet.

    1. HICONS lassen sich nicht vergleichen, weil eben immer neue angelegt werden!
    2. Und wo entsorgst Du bitte das Icon, dass Du durch SHGetFileInfo bekommen hast? Bitte Doku lesen!
    3. Auf SHGFI_SYSICONINDEX habe ich Dich auch schon hingewiesen!



  • Martin Richter schrieb:

    Du solltest genau das tun! Eine map führen in der Du Extension und den vergebenen Index abspeicherst.

    das hab ich soeben erfolgreich implementiert

    Martin Richter schrieb:

    2. Und wo entsorgst Du bitte das Icon, dass Du durch SHGetFileInfo bekommen hast? Bitte Doku lesen!

    stimmt, das hatte ich bisher vergessen, find das nur merkwuerdig da ich das icon nur in der SHFILEINFO struktur habe..

    SHFILEINFO shfi;
    SHGetFileInfo(strFile.c_str(), 0, &shfi, sizeof(SHFILEINFO), SHGFI_ICON);
    .
    .
    DestroyIcon(shfi.hIcon);
    

    Martin Richter schrieb:

    3. Auf SHGFI_SYSICONINDEX habe ich Dich auch schon hingewiesen!

    damit hab ich bisher gar nichts hinbekommen - wuesste nicht wie ich das anwende, habs ja mitlerweile ohne damit funktionstuechtig implementiert


  • Mod

    Selbst wenn das hIcon nur in der Struktur ist, muss es ja jemand freigeben. Es wurde ja für Dich erzeugt!



  • klingt logisch #gg

    wie gesagt, ich hab DestroyIcon bereits gemacht


Anmelden zum Antworten