realMo Posted October 7, 2009 Posted October 7, 2009 I need to get the right icon for all opened windows,you know the ones on the top-left of the title bar(or the ones that you can select when you press Alt-Tab)and use them in my GUI with GUICtrlCreateIcon()This is not as straightforward as I thought, becausegetting the path to the executable is not enough.The icon is often not the first icon in the executable.(For instance c:\WINDOWS\explorer.exe will have a differenticon depending on the directory you select and whether you have folder view open or not.)I found a script on the forum that seemed to solve my problem,( How to use icon handles in ListViews? Not possible? ) but it uses a ListView.The script does find the right icons, but it uses handles to the icons.The script then resets the icons in the ListView using the newly found handles and DllCall()s (which I don't know how to use)Both GUICtrlCreateIcon() and GUICtrlSetImage() can only use thefilename/path of the icon to be loaded.What I need to be able to do is either:A: get the filename of the executable and the icon Nr/ID from the icon handleorB: reset an icon created with GUICtrlCreateIcon() by using an icon handleAnd I have no idea how to do eitherHere's a simplified version of what I'm trying to do:expandcollapse popup#include <GUIConstants.au3> #Include <SendMessage.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", 0) ;Uncomment to run some programs to illustrate the icon problem: ;ShellExecute("C:\WINDOWS\explorer.exe", " C:\") ;==> icon: a hard disk ;ShellExecute("C:\WINDOWS\explorer.exe", " /e, C:\") ;==> icon: an opened folder ;And if D: is you DVD-Drive: ;ShellExecute("C:\WINDOWS\explorer.exe", " C:\WINDOWS") ;==> icon: an opened folder with a magnifying glass ;ShellExecute("C:\WINDOWS\explorer.exe", " D:\") ;==> icon: a CD/DVD $myGUI = GUICreate("First Four Processes", 633, 476, 483, 128) ;Just four icons in this example, set them to make them visible Global $Icons[4] $Icons[0] = GUICtrlCreateIcon("shell32.dll", 24, 80, 40, 80, 80) $Icons[1] = GUICtrlCreateIcon("shell32.dll", 24, 80, 144, 80, 80) $Icons[2] = GUICtrlCreateIcon("shell32.dll", 24, 80, 246, 80, 80) $Icons[3] = GUICtrlCreateIcon("shell32.dll", 24, 80, 348, 80, 80) Global $x=0 $winList = WinList() For $i = 1 To $winList[0][0] $winHandle = $winList[$i][1] $winTitle = $winList[$i][0] If $winTitle <> "" And IsVisible($winHandle) And _ WinGetProcess($winHandle) <> @AutoItPID And $winHandle <> 0 Then $hIcon = getIconHandleByHwnd($winHandle) ;This is where I'm stuck: ;Possible solution A: ;$iconExe = _getIconExeFromHandle($hIcon) ;$iconNr = _getIconNrFromHandle($hIcon) ;Just the first four in this example: $x=$x+1 If $x > 3 Then ExitLoop ;GUICtrlSetImage($Icons[$x], $iconExe, $iconNr) ;Or alternatively, possible solution B something like: ;_resetIcon($Icons[$x], $hIcon) EndIf Next 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 ;==>getExePathByPidThere may be a a third solution that I've overlooked.Any suggestions on how to do this or even where to look for an answer would be greatly appreciated.
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