lod3n Posted February 6, 2007 Share Posted February 6, 2007 (edited) I have been tinkering with something that plays with visible windows, and a window selector I am working on uses a listview. So, I've written a function, getIconHandleByHwnd(), below, that can determine the correct icon to show for each window, but it retrieves an icon handle, not the filename of a icon resource file and index, which is great for Tabs and Menu Items So far as I can determine, and from a great deal of forum searching, the only way to set the icon of a ListView item is with GuiCtrlSetImage, and it ONLY works by means of specifying a specific icon file resource and index number. Does anybody know how to use an icon handle instead? Or, how to convert an icon handle in such a way that it could be used? Google turns up very little, and it sounds like I might be screwed. However! The Applications tab of Task Manager seems to be doing this exact thing, so how the heck do THEY do it? Provided is a scaled down version of the code I'm working on, and a commented out fictional function to set the listview item's icon by icon handle. I am happy writing the function, but I need a lead on how I might do so. expandcollapse popup #include <GUIConstants.au3> #Include <GuiListView.au3> Opt("MustDeclareVars", 0) $guiWinList = GUICreate("Visible Windows") $mylist = GUICtrlCreateListView("Handle |Title ", 10, 10, 380, 380, $LVS_REPORT) $var = WinList() For $i = 1 To $var[0][0] $winHandle = $var[$i][1] $winTitle = $var[$i][0] If $winTitle <> "" And IsVisible($winHandle) And _ WinGetProcess($winHandle) <> @AutoItPID And $winHandle <> 0 Then $lvitem = GUICtrlCreateListViewItem($winHandle & "|" & $winTitle, $mylist) ;set icon traditionaly: GUICtrlSetImage($lvitem, "shell32.dll", 224) ;but I'd rather do this ;~ $hIcon = getIconHandleByHwnd($winHandle);this works elsewhere, for tabs and menu items ;~ SomeFunctionToSetListViewItemIconByIconHandle($mylist,$lvitem,$hIcon) ;~ DestroyIcon($hIcon) EndIf Next _GUICtrlListViewSetColumnWidth($mylist, 0, $LVSCW_AUTOSIZE) _GUICtrlListViewSetColumnWidth($mylist, 1, $LVSCW_AUTOSIZE) GUISetState() While 1 $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd Exit ;required functions Func IsVisible($handle) If BitAND(WinGetState($handle), 2) Then Return 1 Else Return 0 EndIf EndFunc;==>IsVisible Func getIconHandleByFile($pszPath) $SHGFI_ICON = 0x100 ;Get icon $SHGFI_SMALLICON = 0x1 ;Get Small Icon $dwFileAttributes = 0 $psfi = DllStructCreate("uint;int;dword;char[260];char[80]"); thanks Holger! $cbSizeFileInfo = DllStructGetSize($psfi) $uFlags = BitOR($SHGFI_ICON, $SHGFI_SMALLICON) $hImgSmall = DllCall('shell32.dll', 'int', 'SHGetFileInfo', _ 'str', $pszPath, _ 'uint', $dwFileAttributes, _ 'ptr', DllStructGetPtr($psfi), _ 'uint', $cbSizeFileInfo, _ 'uint', $uFlags) Return DllStructGetData($psfi, 1) EndFunc;==>getIconHandleByFile Func getIconHandleByHwnd($hwnd) $hwnd = HWnd($hwnd) $WM_GETICON = 0x7F $GCL_HICONSM = -34 $GCL_HICON = -14 $IDI_APPLICATION = 32512 $hIcon = 0 $hIcon = _SendMessage ($hwnd, $WM_GETICON, False, 0) If ($hIcon == 0) Then $hIcon = _SendMessage ($hwnd, $WM_GETICON, True, 0) If ($hIcon == 0) Then $hIcon = DllCall("user32.dll", "int", "GetClassLong", "hwnd", $hwnd, "int", $GCL_HICONSM) $hIcon = $hIcon[0] EndIf If ($hIcon == 0) Then $hIcon = DllCall("user32.dll", "int", "GetClassLong", "hwnd", $hwnd, "int", $GCL_HICON) $hIcon = $hIcon[0] EndIf If ($hIcon == 0) Then $pid = WinGetProcess(HWnd($hwnd)) $path = getExePathByPid($pid) $hIcon = getIconHandleByFile($path) EndIf Return $hIcon EndFunc;==>getIconHandleByHwnd Func DestroyIcon($hIcon) $bResult = DllCall('user32.dll', 'int', 'DestroyIcon', 'hwnd', $hIcon) Return $bResult[0] EndFunc;==>DestroyIcon Func getExePathByPid($pid) $objWMIService = ObjGet("winmgmts:\\.\root\CIMV2") $colItems = $objWMIService.ExecQuery ("SELECT * FROM Win32_Process WHERE ProcessId = " & $pid, "WQL", 0x10 + 0x20) If IsObj($colItems) Then For $objItem In $colItems Return $objItem.ExecutablePath Next EndIf EndFunc;==>getExePathByPid [code=auto:0] Edit: added line breaks to [ autoit ] and [ code ] tags, funny, I don't remember having to do that in the past. Edited February 6, 2007 by lod3n [font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font] Link to comment Share on other sites More sharing options...
PaulIA Posted February 6, 2007 Share Posted February 6, 2007 If you want to use icon handles, you can do this by loading an ImageList with the icons that you want and then setting the ListView ImageList. I've done this with the Auto3Lib ListView before, so I assume that you can do it with the GUIListView too. If you need help with how to load an icon into a ImageList, take a look at the __ImageList_ReplaceIcon function at the bottom of A3LImageList.au3. Also take a look at _ImageList_AddIcon. I think all you need is the bottom half of that function to do what you want. If you get stuck, give me a shout. Auto3Lib: A library of over 1200 functions for AutoIt Link to comment Share on other sites More sharing options...
lod3n Posted February 6, 2007 Author Share Posted February 6, 2007 (edited) Ah, I didn't know you could replace an imagelist... say, that has interesting possibilities. Excellent! This works nicely, thanks for your help:expandcollapse popup#include <GUIConstants.au3> #Include <GuiListView.au3> Opt("MustDeclareVars", 0) ;$LVM_FIRST = 0x1000 ; defined in GuiListView.au3 $LVM_SETIMAGELIST = $LVM_FIRST + 3 $ILC_MASK = 0x1 $ILC_COLOR32 = 0x20 $ILC_COLOR24 = 0x18 $ILC_PERITEMMIRROR = 0x00008000 $lvFlags = $ILC_COLOR32+$ILC_MASK+$ILC_PERITEMMIRROR $guiWinList = GUICreate("Visible Windows") $mylist = GUICtrlCreateListView("Title |Handle ", 10, 10, 380, 380, $LVS_REPORT) $mylistImageList = DllCall("ComCtl32.dll", "hwnd", "ImageList_Create", "int", 16, "int", 16, "int", $lvFlags, "int", 0, "int", 1) $mylistImageList = $mylistImageList[0] $var = WinList() For $i = 1 To $var[0][0] $winHandle = $var[$i][1] $winTitle = $var[$i][0] If $winTitle <> "" And IsVisible($winHandle) And _ WinGetProcess($winHandle) <> @AutoItPID And $winHandle <> 0 Then $lvitem = GUICtrlCreateListViewItem($winTitle & "|" & $winHandle, $mylist) GUICtrlSetImage($lvitem, "shell32.dll", 224);have to set something, or there'll be no image list to swap out! $hIcon = getIconHandleByHwnd($var[$i][1]) $nIndex = DllCall('comctl32.dll', 'int', 'ImageList_AddIcon', 'hwnd', $mylistImageList, 'hwnd', $hIcon) DllCall('user32.dll', 'int', 'DestroyIcon', 'hwnd', $hIcon) EndIf Next _SendMessage(GUICtrlGetHandle($mylist), $LVM_SETIMAGELIST, 1, $mylistImageList) _GUICtrlListViewSetColumnWidth($mylist, 0, $LVSCW_AUTOSIZE) _GUICtrlListViewSetColumnWidth($mylist, 1, $LVSCW_AUTOSIZE) GUISetState() While 1 $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd Exit ;required functions Func IsVisible($handle) If BitAND(WinGetState($handle), 2) Then Return 1 Else Return 0 EndIf EndFunc ;==>IsVisible Func getIconHandleByFile($pszPath) $SHGFI_ICON = 0x100 ;Get icon $SHGFI_SMALLICON = 0x1 ;Get Small Icon $dwFileAttributes = 0 $psfi = DllStructCreate("uint;int;dword;char[260];char[80]") ; thanks Holger! $cbSizeFileInfo = DllStructGetSize($psfi) $uFlags = BitOR($SHGFI_ICON, $SHGFI_SMALLICON) $hImgSmall = DllCall('shell32.dll', 'int', 'SHGetFileInfo', _ 'str', $pszPath, _ 'uint', $dwFileAttributes, _ 'ptr', DllStructGetPtr($psfi), _ 'uint', $cbSizeFileInfo, _ 'uint', $uFlags) Return DllStructGetData($psfi, 1) EndFunc ;==>getIconHandleByFile Func getIconHandleByHwnd($hwnd) $hwnd = HWnd($hwnd) $WM_GETICON = 0x7F $GCL_HICONSM = -34 $GCL_HICON = -14 $IDI_APPLICATION = 32512 $hIcon = 0 $hIcon = _SendMessage ($hwnd, $WM_GETICON, False, 0) If ($hIcon == 0) Then $hIcon = _SendMessage ($hwnd, $WM_GETICON, True, 0) If ($hIcon == 0) Then $hIcon = DllCall("user32.dll", "int", "GetClassLong", "hwnd", $hwnd, "int", $GCL_HICONSM) $hIcon = $hIcon[0] EndIf If ($hIcon == 0) Then $hIcon = DllCall("user32.dll", "int", "GetClassLong", "hwnd", $hwnd, "int", $GCL_HICON) $hIcon = $hIcon[0] EndIf If ($hIcon == 0) Then $pid = WinGetProcess(HWnd($hwnd)) $path = getExePathByPid($pid) $hIcon = getIconHandleByFile($path) EndIf Return $hIcon EndFunc ;==>getIconHandleByHwnd Func getExePathByPid($pid) $objWMIService = ObjGet("winmgmts:\\.\root\CIMV2") $colItems = $objWMIService.ExecQuery ("SELECT * FROM Win32_Process WHERE ProcessId = " & $pid, "WQL", 0x10 + 0x20) If IsObj($colItems) Then For $objItem In $colItems Return $objItem.ExecutablePath Next EndIf EndFunc ;==>getExePathByPid Edited February 7, 2007 by lod3n [font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font] Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now