Hi,

I try to load all possible icons from SHELL32.DLL into an imagelist.
It works, but most icons looks shitty. Same of them have big black borders and some of them are pixeled out.
Is there a better method to put the shell32.dll-icons in the imagelist ?

Sorry for my bad english...



invoke GetSystemMetrics,49
mov xxx,eax
invoke GetSystemMetrics,50
mov yyy,eax

invoke ImageList_Create,xxx,yyy,33,0,0 ;1
mov ilist,eax

invoke GetSystemDirectory,addr unwichtig,512
invoke szCatStr,addr unwichtig,addr shelltext
invoke LoadLibrary,addr unwichtig
mov shell32,eax

mov ecx,1
zander:
push ecx
invoke LoadIcon,shell32,ecx
pop ecx
cmp eax,0
je endezander
push ecx
invoke ImageList_AddIcon,ilist,eax
pop ecx
inc ecx
jmp zander

endezander:


Greetings,
Nordwind64
Posted on 2003-02-12 09:04:59 by Nordwind64
Why not use the system image list, that way your icons can look the same as the standard icons on every operating system. Use the following, where szFileName can be anything (I use c:\\):



SHFILEINFO psfi;

hImageList = (HIMAGELIST)SHGetFileInfo(szFileName, 0, &psfi,
sizeof(SHFILEINFO), SHGFI_ICON | SHGFI_SYSICONINDEX | HGFI_SMALLICON );
ListView_SetImageList(hList, hImageList, LVSIL_SMALL);


Use the following to get the index in the image list of each filename:



SHGetFileInfo(szFileName, 0, &psfi, sizeof(SHFILEINFO), SHGFI_ICON);


Where psfi.iIcon is the index of the icon in the system image list. Make sure your list control has the LVS_SHAREIMAGELISTS style and don't destory the image list at the end.

Nick
Posted on 2003-02-12 09:19:28 by Nick
Thank you Nick !!!

I've tested this/your method before, but I never could get more than 5 icons in my imagelist...
C:\\ don't work, C:\ does, but only 5 icons...
I have Windows XP Home

Can you please post me an full example ? I cannot find my error...

Greetings,
Nordwind64
Posted on 2003-02-12 14:14:46 by Nordwind64
First, you have to get the handle to the system image list (either large or small icons, your choice), we do this by passing a known folder/drive to the api I usually pass my app path. (I don't use c:\ here because not everyone has a c:\, I had em e:,f:,g: at one time)


push SHGFI_SMALLICON\
or SHGFI_SYSICONINDEX
push sizeof sfi
lea eax, sfi
push eax
push 0
push offset AppPath
call SHGetFileInfo
mov imlListView, eax ; store the system image list handle for our Listview imagelist


Now you can create your Listview (with the share imagelist flag) and associate imlListView (which is the handle to the system imagelsit) with your listview.
i.e.


; #######################################
; ###### Create listview
push 0
push hInstance
push IDC_LV_MAIN
push hWnd
push 0
push 0
push 0
push 255
push WS_CHILD\
or WS_VISIBLE\
or LVS_REPORT\
or LVS_SHAREIMAGELISTS ; <<< this is important Nordwind64 if you are using the system image list!
push 0
push offset WndClsListView
push WS_EX_CLIENTEDGE
call CreateWindowEx
mov hLVMain, eax

push imlListView
push LVSIL_SMALL
push LVM_SETIMAGELIST
push hLVMain
call SendMessage ; Set listview imagelist to system imagelist


Remember, do not destroy the image list you set to your listview, or all your icons will be gone in the os...
Now your listview will use the same imagelist that explorer uses to show icons.
HTH
Posted on 2003-02-12 14:50:07 by Gunner
Hi,

I found a much better way, an undokumented shell32.dll function (660), that forces Nt-based Windows to fill the system imagelist with ALL available icons...
Thanks to all !

Greetings,
Nordwind64
Posted on 2003-02-13 13:05:04 by Nordwind64
"much better" and "undocumented" in the same sentence? hmm.
Posted on 2003-02-13 13:08:10 by f0dder
Hi fodder,

without this function I only could get 5 icons (Windows XP) in the system imagelist, with the 660-function I get 95 icons, fast and in best quality...
Not bad for some lines of code ;-)



invoke LoadLibrary,addr dllname
mov shell32,eax

invoke GetProcAddress,shell32,660

.if eax!=0
push 1
call eax
.endif


Greetings,
Nordwind64
Posted on 2003-02-13 14:12:36 by Nordwind64
true... if you're only using it to *get* the icons it's fine... but if you're going to use the code in a production app... ick :)
Posted on 2003-02-13 14:13:58 by f0dder
Hi,

> production app <

Sorry ?
What do you mean ? My english is not as good as it should be...
Posted on 2003-02-13 14:47:31 by Nordwind64
I mean that using undocumented calls like that is fine if you're only going to grab the imagelist to cut out some icons for later... not in an application that leaves your computer.
Posted on 2003-02-13 14:51:06 by f0dder
Production app means an app you are releasing to the public. Undocumented functions are fine for your own use on your computer, but being they are undocumented, there is no guarantee the function exists/will exist in all windows versions.
Posted on 2003-02-13 14:52:13 by Gunner
Hi,

aha, thank you, ok.
I will test it on all platforms.

Greetings,
Nordwind64
Posted on 2003-02-13 23:31:06 by Nordwind64
testing on all platforms is not enough as long as the function is undocumented - it might be gone in the next windows version without notice.
Posted on 2003-02-14 01:26:26 by f0dder
Gunner,

I tried your code in a listview process viewer of mine and I now have icons, but they're all the same default icon. I suppose I need to index into the image list with SHGetFileInfo as suggested by Nick ?
Posted on 2003-02-14 07:46:58 by gscundiff
F0dder, I think M$ only isn't interested in making the function public. But I'm sure, this function will be in the next windows versions... However, I use this method and two other methods for ripping icons..

Greetings,
Nordwind64
Posted on 2003-02-14 08:01:13 by Nordwind64
gscundiff,

Now that you have the system imagelist associated with your listview, you can now do a SHGetFileInfo with either a path to a folder, full file path or a file extension to get the correct icon in your listview. Here is an example:

Create your listview with one column and try the below,
sfi = SHFILEINFO
lvi = LVITEM
dwIndex = index of current listview item inserting
FilePath = a valid path to any existing file



push SHGFI_SYSICONINDEX\
or SHGFI_USEFILEATTRIBUTES
push sizeof sfi
lea eax, sfi
push eax
push 0
push offset FilePath
call SHGetFileInfo

mov lvi.imask, LVIF_IMAGE\
or LVIF_TEXT
push sfi.iIcon
pop lvi.iImage
push dwIndex
pop lvi.iItem
mov lvi.iSubItem, 0
lea eax, FilePath
push lvi.pszText

lea ecx, lvi
push ecx
push 0
push LVM_INSERTITEM
push hListView
call SendMessage

To get the icons for html files, just pass .html for the FilePath
To get the icon for a folder pass SHGFI_SYSICONINDEX Or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES for the flags.

The important thing here is not to destroy the image list.

HTH
Posted on 2003-02-14 08:55:05 by Gunner
Gunner,

Thank you very much for your explanation. I am now able to retrieve and display the proper icons in my listview...something I've had an exhausting struggle with for a few sessions.:alright:
Posted on 2003-02-14 10:42:36 by gscundiff