i've managed display icons files in listview using shell32 extraction, when folders, icon doesn't seem show. how be?
this shell extraction code:
' declare win32 api function shgetfileinfo' public declare auto function shgetfileinfo lib "shell32.dll" (byval pszpath string, byval dwfileattributes integer, byref psfi shfileinfo, byval cbfileinfo integer, byval uflags integer) intptr ' declare constants shgetfileinfo requires' public const shgfi_icon integer = &h100 public const shgfi_smallicon integer = &h1 ' define shfileinfo structure' structure shfileinfo public hicon intptr public iicon integer public dwattributes integer <runtime.interopservices.marshalas(runtime.interopservices.unmanagedtype.byvaltstr, sizeconst:=260)> _ public szdisplayname string <runtime.interopservices.marshalas(runtime.interopservices.unmanagedtype.byvaltstr, sizeconst:=80)> _ public sztypename string end structure function retrieveshellicon(byval argpath string) image dim mshellfileinfo shfileinfo dim msmallimage intptr dim micon system.drawing.icon dim mcompositeimage image mshellfileinfo = new shfileinfo mshellfileinfo.szdisplayname = new string(chr(0), 260) mshellfileinfo.sztypename = new string(chr(0), 80) msmallimage = shgetfileinfo(argpath, 0, mshellfileinfo, system.runtime.interopservices.marshal.sizeof(mshellfileinfo), shgfi_icon or shgfi_smallicon) ' create icon icon handle' try micon = system.drawing.icon.fromhandle(mshellfileinfo.hicon) mcompositeimage = micon.tobitmap catch ex exception ' create blank black bitmap return' mcompositeimage = new bitmap(16, 16) end try ' return composited image' return mcompositeimage end function function geticon(byval argfilepath string) image dim mfileextension string = system.io.path.getextension(argfilepath) ' add image if doesn't exist'' if cicons.containskey(mfileextension) = false cicons.add(mfileextension, retrieveshellicon(argfilepath)) end if ' return image' return cicons(mfileextension) end function
and how show icon files.
dim lvi listviewitem dim di new directoryinfo(form2.textbox1.text) dim exts new list(of string) imagelist1.images.clear() if di.exists = false messagebox.show("source path not found", "directory not found", messageboxbuttons.ok, messageboxicon.error) else each fi fileinfo in di.enumeratefiles("*.*") lvi = new listviewitem lvi.text = fi.name lvi.subitems.add(((fi.length / 1024)).tostring("0.00")) lvi.subitems.add(fi.creationtime) if exts.contains(fi.extension) = false dim mshelliconmanager new form1 each mfilepath string in my.computer.filesystem.getfiles(form2.textbox1.text) imagelist1.images.add(fi.extension, geticon(mfilepath)) exts.add(fi.extension) next end if lvi.imagekey = fi.extension listview1.items.add(lvi) next
this how show folder icons doesn't seem work
for each fldr string in directory.getdirectories(form2.textbox1.text) dim mshelliconmanager new form1 lvi = new listviewitem lvi.text = path.getfilename(fldr) lvi.subitems.add(((fldr.length / 1024)).tostring("0.00")) lvi.subitems.add(directory.getcreationtime(fldr)) imagelist1.images.add(geticon(fldr)) listview1.items.add(lvi) next
there couple of things in code. of looks remnants previous attempts. @ rate, works:
public partial class nativemethods private const max_path integer = 256 private const namesize integer = 80 private const shgfi_icon int32 = &h100 <structlayout(layoutkind.sequential)> private structure shfileinfo public hicon intptr public iicon integer public dwattributes integer <marshalas(unmanagedtype.byvaltstr, sizeconst:=max_path)> public szdisplayname string <marshalas(unmanagedtype.byvaltstr, sizeconst:=namesize)> public sztypename string end structure <dllimport("shell32.dll")> private shared function shgetfileinfo(pszpath string, dwfileattributes integer, byref psfi shfileinfo, cbfileinfo integer, uflags integer) intptr end function <dllimport("user32.dll", setlasterror:=true)> private shared function destroyicon(hicon intptr) boolean end function public shared function getshellicon(path string) bitmap dim shfi shfileinfo = new shfileinfo() dim ret intptr = shgetfileinfo(path, 0, shfi, marshal.sizeof(shfi), shgfi_icon) if ret <> intptr.zero dim bmp bitmap = system.drawing.icon.fromhandle(shfi.hicon).tobitmap destroyicon(shfi.hicon) return bmp else return nothing end if end function end class
putting pinvoke code in own class has several benefits. first, helps isolate code form magic numbers, structures , constants. pinvoke(s) can private , exposed thru method (getshellicon
) scut work , invokes api method. also, vs codeanalysis tool wont complain when used nativemethods
class.
one of things code not doing destroying icon retrieved , releasing resource; shgetfileinfo
doesn't right can lead bad things. when can't icon, not create blank/empty bitmap in pinvoke code, instead returns nothing
code handle.
in end, easier use , shorter pinvoke code encapsulated:
dim fpath string = "c:\temp" dim di = new directoryinfo(fpath) ' store imagelist index known/found file types dim exts new dictionary(of string, int32) dim img image dim lvi listviewitem each d in di.enumeratedirectories("*.*", searchoption.topdirectoryonly) lvi = new listviewitem(d.name) lvi.subitems.add("") ' no file name lvi.subitems.add(directory.getfiles(d.fullname).count().tostring) mylv.items.add(lvi) img = nativemethods.getshellicon(d.fullname) imglst.images.add(img) lvi.imageindex = imglst.images.count - 1 next each f in di.enumeratefiles("*.*") lvi = new listviewitem(f.directoryname) lvi.subitems.add(f.name) ' no file name lvi.subitems.add("n/a") mylv.items.add(lvi) if exts.containskey(f.extension) = false ' try simplest method img = drawing.icon.extractassociatedicon(f.fullname).tobitmap if img nothing img = nativemethods.getshellicon(f.fullname) end if if img isnot nothing imglst.images.add(img) exts.add(f.extension, imglst.images.count - 1) else ' ?? use default or custom '?' one? end if end if lvi.imageindex = exts(f.extension) next
for file, first tries icon using net icon.extractassociatedicon
method , resorts pinvoke of failed reason.
i changed exts
list(of string
dictionary(of string, int32)
. once code gets icon extension, saves index of image in imagelist
extension/icon doesn't need looked again. speeds quite bit on large folders.
if declare dictionary
outside method , don't clear imagelist
each time, let them both accumulate images runs. text file
icon in folder foo
wont different image text files else where.
Comments
Post a Comment