Hi, I'm trying to show some system icons in a listview, but I get some Access Violations... any clue?
$INCLUDE "WindowsSDK.inc"
$INCLUDE "commoncontrols.inc"
$INCLUDE "CommCtrl.inc"
CONST LISTVIEW_1 = 1
DIALOG d1
CREATEDIALOG d1,0,0,690,422,0x80C80080,0,"Caption",&d1_handler
CONTROL d1,@LISTVIEW,"",13,11,662,393,0x50000001,LISTVIEW_1
DOMODAL d1
SUB d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW d1
/* Initialize any controls here */
INT himl = GetSystemImageList(1)
IF himl THEN
ListviewSetImageList( GETCONTROLHANDLE(d1, LISTVIEW_1) , himl)
ListviewAddItem( GETCONTROLHANDLE(d1, LISTVIEW_1), 1, "first", 1)
ENDIF
CASE @IDCLOSEWINDOW
CLOSEDIALOG d1,@IDOK
CASE @IDCONTROL
SELECT @CONTROLID
CASE LISTVIEW_1
/* respond to control notifications here */
ENDSELECT
ENDSELECT
RETURN
ENDSUB
SUB GetSystemImageList(int size), INT
HRESULT hr
INT sizeflag
pointer ppvObj
INT himl = 0
SELECT size
CASE 1
sizeflag = SHIL_SMALL
CASE 2
sizeflag = SHIL_LARGE
DEFAULT
sizeflag = SHIL_EXTRALARGE
ENDSELECT
hr = SHGetImageList(sizeflag, _IID_IImageList, &ppvObj)
IF hr = S_OK THEN himl = *<int> ppvObj
RETURN himl
ENDSUB
SUB ListviewSetImageList(int hwndlv, int himl), INT
RETURN SendMessage(hwndlv, LVM_SETIMAGELIST , LVSIL_NORMAL, himl)
ENDSUB
SUB ListviewAddItem(int hwndlv, int npos, string text, int nimage), INT
LVITEM lvit
lvit.mask= LVIF_IMAGE | LVIF_TEXT
lvit.iItem=npos-1
lvit.iSubItem=0
lvit.pszText=text
lvit.iImage=nimage-1
RETURN SendMessageA(hwndlv, LVM_INSERTITEM, 0, &lvit)
ENDSUB
This is an old program by Sapero that may help you.
WINDOW d1
STRING name
UINT himl_Big, himl_Small, lvView
TYPE LVITEM /*saved space :) */
UINT mask
INT iItem[4]
POINTER pszText[2]
INT iImage[6]
ENDTYPE
TYPE LVBKIMAGE /*saved space :) */
UINT ulFlags[2]
POINTER pszImage[4]
ENDTYPE
Const ID_TCOLOR = 44442
Const ID_BCOLOR = 44443
Const ID_PAPER = 44444
Const ID_NEW = 44445
Const ID_BIG = 0x1000
Const ID_REPORT = 0x1001
Const ID_SMALL = 0x1002
Const ID_LIST = 0x1003
Const LVS_ICON = 0
Const LVS_REPORT = 1
Const LVS_SMALLICON = 2
Const LVS_LIST = 3
Declare import, GetSystemDirectory alias GetSystemDirectoryA(lpBuffer:pointer, nSize:int),int
Declare import, ScreenToClient(hwnd:uint, POINT:pointer),int
Declare import, GetCursorPos(POINT:pointer),int
Declare import, GetWindowLong alias GetWindowLongA(hwnd:uint, nIndex:int),uint
Declare import, SetWindowLong alias SetWindowLongA(hWnd:uint, nIndex:int, dwNewLong:uint),uint
Declare import, ZeroMemory alias RtlZeroMemory(dat:uint, length:int),int
Declare import, InvalidateRect(hwnd:uint, opt WINRECT:pointer, opt bErase=TRUE:int),int
Declare import, DestroyIcon(hIcon:uint),int
'Declare import, ImageList_Create(cx:int, xy:int, flags:uint, cInitial:int, cGrow:int),uint
'Declare import, ImageList_ReplaceIcon(himl_Big:uint, position:int, hIcon:uint),int
'Declare import, ImageList_Destroy(himl_Big:uint),int
'Declare import, ImageList_Remove(himl_Big:uint,position:int),int
Declare import, ExtractIconEx alias ExtractIconExA(filename:pointer, index:int, _
pArrayLarge:pointer, pArraySmall:pointer, nIcons:int),int
openwindow d1,0,0,700,500,@caption|@sysmenu|@minbox|@maxbox|@size,0,"Right click on listview to select file",&winproc
CONTROL d1,@LISTVIEW,"",0,0,856,60,0x50000101,1
controlcmd d1,1,@lvinsertcolumn, 0, "all the icons"
controlcmd d1,1,@lvsetcolwidth,0,200
sizelv()
/* lets go! create image list */
himl_Big = ImageList_Create(32, 32, 0x21/*ILC_COLOR32|ILC_MASK*/, 150, 150)
himl_Small = ImageList_Create(16, 16, 0x21, 150, 150)
sendmessage d1, 4099/*LVM_SETIMAGELIST*/, 0/*LVSIL_NORMAL*/, himl_Big, 1
sendmessage d1, 4099, 1/*LVSIL_SMALL*/, himl_Small, 1
SetView(LVS_ICON)
/* insert all icons from %systemdir%/shell32.dll */
GetSystemDirectory(name, 255-12)
name+="\\shell32.dll"
LoadIcons()
ChangeWallpaper("http://www.pyxia.com/images/pyxiabanner1.gif")
ChangeColor(1, 0xFFFFFF)
waituntil d1.hwnd=0
end
sub winproc
select @message
case @idcreate
centerwindow d1
CoInitialize(NULL)
case @idclosewindow
ImageList_Destroy(himl_Big)
ImageList_Destroy(himl_Small)
CoUninitialize()
closewindow d1
case @idsize
sizelv()
case @idcontrol
select @controlid
case 1
if @notifycode = @NMRCLICK
doContextMenu()
endif
endselect
case @idmenupick
select @menunum
case ID_BCOLOR : ChangeColor()
case ID_TCOLOR : ChangeColor(1)
case ID_PAPER : ChangeWallpaper()
case ID_NEW : LoadIcons()
' case ID_BIG : SetView(LVS_ICON)
' case ID_SMALL : SetView(LVS_SMALLICON)
' case ID_LIST : SetView(LVS_LIST)
' case ID_REPORT : SetView(LVS_REPORT)
case ID_BIG
case& ID_SMALL
case& ID_LIST
case& ID_REPORT : SetView(@menunum&3)
endselect
endselect
return
endsub
sub sizelv
INT l,t,w,h
getclientsize d1,l,t,w,h
setsize d1,0,0,w,h,1
return
endsub
sub doContextMenu
POINT pt
GetCursorPos(pt)
ScreenToClient(d1.hwnd, pt)
ContextMenu d1, pt.x, pt.y
Menuitem "Change background color", 0, ID_BCOLOR
Menuitem "Change text color", 0, ID_TCOLOR
Menuitem "Set Wallpaper", 0, ID_PAPER
Separator
Menuitem "Load new icon file", 0, ID_NEW
Separator
Menuitem "View: Icons", (lvView=LVS_ICON)<<3, ID_BIG
Menuitem "View: Small Icons", (lvView=LVS_SMALLICON)<<3, ID_SMALL
Menuitem "View: List", (lvView=LVS_LIST)<<3, ID_LIST
Menuitem "View: Report", (lvView=LVS_REPORT)<<3, ID_REPORT
Endmenu
return
endsub
sub ChangeColor(opt bg:int, opt colorref=-1:int)
INT colo, hwnd
hwnd = getcontrolhandle(d1, 1)
colo = sendmessage(d1, 4096/*LVM_GETBKCOLOR*/, 0,0, 1)
if colorref = -1
colo = colorrequest(d1, colo)
else
colo = colorref
endif
if bg = 0
sendmessage d1, 4097/*LVM_SETBKCOLOR*/, 0, colo, 1
sendmessage d1, 4134/*LVM_SETTEXTBKCOLOR*/, 0, colo, 1
else
sendmessage d1, 4132/*LVM_SETTEXTCOLOR*/, 0, colo, 1
endif
InvalidateRect(hwnd, NULL, TRUE)
return
endsub
Sub LoadIcons
LVITEM lvi
ZeroMemory(&lvi, 52)
UINT IconBig[512], IconSmall[512], count, a
ISTRING itemtxt[64]
if name[0]=0 then name = filerequest("", d1, 1, _
"exe,dll,ocx,sys,ico|*.exe;*.dll;*.ocx;*.sys;*.ico||")
if name[0]<>0
count = ExtractIconEx(name, 0, IconBig, IconSmall, 512)
ImageList_Remove(himl_Big, -1) /* remove all icons */
ImageList_Remove(himl_Small, -1)/* from imagelist */
CONTROLCMD d1,1, @LVDELETEALL
SetCaption d1, using("& total # icons", name, count)
lvi.mask = 3 /* LVIF_TEXT | LVIF_IMAGE*/
lvi.pszText = itemtxt
lvi.iImage = -1
lvi.iItem = -1
count--
for a = 0 to count
if a=0 then seticon d1, IconSmall[0]
ImageList_ReplaceIcon(himl_Big, -1, IconBig[a]) /* add icon */
ImageList_ReplaceIcon(himl_Small, -1, IconSmall[a])
itemtxt = using("icon #", a)
lvi.iImage++
lvi.iItem++
SendMessage d1, 4103/*LVM_INSERTITEM*/, 0, &lvi, 1
DestroyIcon(IconBig[a])
DestroyIcon(IconSmall[a])
next a
endif
name[0] = 0
return
EndSub
sub SetView(view:int)
UINT hwnd, style
hwnd = getcontrolhandle(d1, 1)
lvView = view
style = GetWindowLong(hwnd, -16/*GWL_STYLE*/) & -4 | view
SetWindowLong(hwnd, -16, style)
return
EndSub
sub ChangeWallpaper(opt location:string)
ISTRING path[260]
POINTER p
LVBKIMAGE lbgi
ZeroMemory(&lbgi, 24)
p = location
IF p <> NULL
path = location
else
path = filerequest("", d1, 1, "bitmaps|*.bmp||")
endif
if path[0] <> 0
lbgi.pszImage = path
lbgi.ulFlags = 0x12 /*LVBKIF_STYLE_TILE | LVBKIF_SOURCE_URL*/
if sendmessage(d1, 4164/*LVM_SETBKIMAGE*/, 0, &lbgi, 1) = FALSE
messagebox d1, "cannot set new image", ""
endif
endif
return
EndSub
LarryMc
Hi Larry, I have to reformulate my question, because it is wrong. The only thing that interests me in my example is the GetSystemImageList(...) function, the rest is just to check it out this function :)
I need the handle of the system image list. I know that I can get the system Imagelist using SHGetFileInfo(...), but I am interested in extra big icons (SHIL_EXTRALARGE flag of SHGetImageList(...) ).
However, the example you've provided have some nice stuff, and it will serve to me as a future reference, thanks again Larry :)
Ha! I haven't solved anything complex in awhile so this was a fun one. Glad I have internet at home now, I surely needed it!
Left Click the window and itll show the image specified at the index.
Okay heres the working example:
$Include "windows.inc"
$Define SHIL_EXTRALARGE 2
$Define ILD_NORMAL 0
Declare Import,SHGetImageList(iImageList As Int,riid As GUID,ppv As Pointer),UInt
Dim wndMain As Window
Dim IID_IImageList As GUID
Define_GUID(IID_IImageList,0x46EB5926,0x582E,0x4017,0x9F,0xDF,0xE8,0x99,0x8D,0xAA,0x09,0x50)
OpenWindow wndMain,0,0,640,480,@MinBox,0,"SHGetImageList",&wndMainProc
WaitUntil IsWindowClosed wndMain
End
Sub wndMainProc
Dim List=0,hdc As UInt
Select @Message
Case @IDLButtonDN
If SHGetImageList(SHIL_EXTRALARGE,IID_IImageList,List)=S_OK Then
hdc=GetHDC(wndMain)
If List And hdc Then
SetCaption wndMain,"List count:"+Str$(ImageList_GetImageCount(List))
_ImageList_Draw(List,0,hdc,0,0,ILD_NORMAL)
_ImageList_Destroy(List)
ReleaseHDC(wndMain,hdc)
Else
MessageBox wndMain,"List:"+Hex$(List)+"\nhdc:"+Hex$(hdc),"Error"
EndIf
Else
MessageBox wndMain,"SHGetImageList failed.","Error"
EndIf
Case @IDCloseWindow
CloseWindow wndMain
EndSelect
EndSub
I didn't really try to debug your original code, because that can confuse me sometimes when working with new APIs. I'm not sure what you were doing wrong, however I purposely defined the GUID on my own since I saw here:
http://www.ms-news.net/f2749/shgetimagelist-iid_iimagelist-4101385.html
That the predefined GUID was wrong for someone else, also I couldn't find a data structure for HIMAGELIST so I dug a little and found theres a suite of function for using these lists. Basically I get the impression that you can't really cast the returned pointer as an HIMAGELIST, everything that will accept this type of variable is actually a COM wrapper. Trying to access this as readable data would conceivable cause access violations though I didn't test it.
Hope this helps :)
Nice, you really save me this time. I'll be out two weeks and I'm happy that I can finish this before.
The example works perfectly, I even tested it with:
$Define SHIL_JUMBO 4
on a pc with win7 and draw a 256 x 256 icon!
Respect to the cast, I was thinking too that I can not make the cast of the returned pointer as an HIMAGELIST, or at least I'm pretty sure the problem is in there.
But the most important thing is that you've found a solution.
Thanks, Wayne!