Jump to content

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies. Find out more here. X
X


Photo

Get Systray Icons [Solved]


  • Please log in to reply
10 replies to this topic

#1 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,402 posts

Posted 05 November 2011 - 02:53 PM

For my current Project HMW - Hide my Windows (to be renamed accordingly on the next release :D ) I'm looking for a way to acquire the Systray Icons. For fetching infos on the Systray buttons I use wraithdu's excellent _SysTray UDF. Using the _SysTrayGetButtonInfo() function it is possible to get the Imagelist index for the buttons, but as the Imagelist is being created by explorer.exe there seems to be no easy way to access that list. I've found some postings around the net mentioning dll injection... but I find that idea quite disturbing. Currently I'm fetching the file icons of the underlying processes, but sadly those often do not match the ones display in the Systray.

I've run out of ideas on this one, maybe someone else has done some investigation on this already :oops:?

Edited by KaFu, 20 December 2011 - 01:37 PM.








#2 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,402 posts

Posted 09 November 2011 - 09:09 AM

Anyone :D?

#3 careca

careca

    =)

  • Active Members
  • PipPipPipPipPipPip
  • 820 posts

Posted 09 November 2011 - 01:19 PM

Ok, 1 idea, maybe you can use _SysTray UDF to find out the path to the exe, extract the ico from the exe, or extract the bmp, convert it to ico and use it?

Currently I'm fetching the file icons of the underlying processes, but sadly those often do not match the ones display in the Systray.


Yeah, that might happen, oh well, its better some icon than no icon.

BeatsPlayer - My Music player

 

"Know what really grinds my gears? Those people who quote whole posts for no reason." Peter Griffin


#4 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,402 posts

Posted 09 November 2011 - 01:31 PM

Thanks for the feedback, that's exactly what I'm currently doing, but fetching the ones that are actually displayed would be much nicer. Searched a little more and only found solutions where custom dlls are being injected into the “explorer.exe” process. I neither can create such a dll nor do I think it’s a nice behavior :D...

Edited by KaFu, 09 November 2011 - 01:31 PM.


#5 rover

rover

    unmutual

  • Active Members
  • PipPipPipPipPipPip
  • 825 posts

Posted 20 December 2011 - 01:22 PM

For my current Project HMW - Hide my Windows (to be renamed accordingly on the next release :) ) I'm looking for a way to acquire the Systray Icons. For fetching infos on the Systray buttons I use wraithdu's excellent _SysTray UDF. Using the _SysTrayGetButtonInfo() function it is possible to get the Imagelist index for the buttons, but as the Imagelist is being created by explorer.exe there seems to be no easy way to access that list. I've found some postings around the net mentioning dll injection... but I find that idea quite disturbing. Currently I'm fetching the file icons of the underlying processes, but sadly those often do not match the ones display in the Systray.

I've run out of ideas on this one, maybe someone else has done some investigation on this already ;)?

Greetings KaFu

You can get most* of the icons from the notification area using shared memory code.
The traydata struct in the TBBUTTON/TBBUTTONINFO structs Param element has a handle to the toolbar button icon.
The traydata struct is undocumented but works in XP, Vista and Win 7 x86/x64
I use this in my _RefreshNotificationAreaIcons and _RefreshTrayIcon() UDFs

The SysTray UDF only retrieves the owner window handle from the traydata struct.

Get and use Imagelist From Another Process
http://www.xtremevbtalk.com/showthread.php?t=128730
I ran the above struct code, and it does return some systray (XP) imagelist info (image count, icon size, etc.).
The bitmap and memdc handles as mentioned are not accessible outside of the explorer process.
The imagelist struct is different from the standard imagelist, _GUICtrlToolbar_GetImageList returns a handle,
but ImageList_GetImageCount() returns 0.

*As pointed out in that vb forum, some apps that frequently update their icons (temp, cpu use, etc.)
will update the icon image in the notification areas imagelist with Shell_NotifyIcon + NIM_MODIFY,
then destroy the icon handle, so the notification area imagelist has the current icon, but the handle in the traydata struct is not valid.
Taskmgr replacements Process Explorer and Process Hacker 2 have process history tray icons that return invalid icon handles.

I wrote some tray icon retrieval code a few years back, here's an updated example.
For XP/2003,Vista/2008,Win7/2008R2 x86/x64

AutoIt         
;coded by rover 2k11 #NoTrayIcon #Include <WinAPIEx.au3> #include <WinAPI.au3> #include <Process.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include <Constants.au3> #Include <APIConstants.au3> #include <WindowsConstants.au3> #Include <ToolBarConstants.au3> #Include <ProcessConstants.au3> #include <MemoryConstants.au3> Opt("MustDeclareVars", 1) Global Const $PROCESS_ACCESS = BitOR($PROCESS_VM_OPERATION, $PROCESS_VM_READ) Global $iTbar = 0 Global $hOwnerWin, $hTrayWnd, $hTrayNotifyWnd, $hSysPager, $hToolbar, _   $iDLLUser32 = DllOpen("user32.dll"), $iDLLKrnl32 = DllOpen("kernel32.dll"), _   $tTBBUTTON, $pTBBUTTON, $iTBBUTTON, $tTRAYDATA, $pTRAYDATA, $iTRAYDATA, _   $iImg = 0, $iIdx = 0, $iCount, $iPIDExp, $hProcess, $pAddress, $iPID, $aRet, $sRet, $hIconTray, $hIcon $hTrayWnd = WinGetHandle("[CLASS:Shell_TrayWnd]") $hTrayNotifyWnd = ControlGetHandle($hTrayWnd, "", "[CLASS:TrayNotifyWnd]") $hSysPager = ControlGetHandle($hTrayNotifyWnd, "", "[CLASS:SysPager]") $hToolbar = ControlGetHandle($hSysPager, "", "[CLASS:ToolbarWindow32; INSTANCE:1]");User Promoted Notification Area/Notification Area/SysTray Switch @OSVersion Case "WIN_2008R2", "WIN_7"   Switch $iTbar    Case 1 ;Overflow Notification Area     $hToolbar = ControlGetHandle(WinGetHandle("[CLASS:NotifyIconOverflowWindow]"), "", "[CLASS:ToolbarWindow32; INSTANCE:1]")    Case 2 ;System Promoted Notification Area     $hToolbar = ControlGetHandle($hTrayNotifyWnd, "", "[CLASS:ToolbarWindow32; INSTANCE:2]")   EndSwitch EndSwitch $tTBBUTTON = DllStructCreate("int Bitmap;int Command;byte State;byte Style;align;dword_ptr Param;int_ptr String") $pTBBUTTON = DllStructGetPtr($tTBBUTTON) $iTBBUTTON = DllStructGetSize($tTBBUTTON) $tTRAYDATA = DllStructCreate("hwnd hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];ptr hIcon") $pTRAYDATA = DllStructGetPtr($tTRAYDATA) $iTRAYDATA = DllStructGetSize($tTRAYDATA) $iPIDExp = WinGetProcess($hToolbar) If @error Or $iPIDExp = -1 Then exit $aRet = DllCall($iDLLKrnl32, "ptr", "OpenProcess", "dword", _   $PROCESS_ACCESS, "int", 0, "int", $iPIDExp) If @error Or $aRet[0] = 0 Then Exit $hProcess = $aRet[0] $aRet = DllCall($iDLLUser32, "lparam", "SendMessageW", "hwnd", _   $hToolbar, "int", $TB_BUTTONCOUNT, "wparam", 0, "lparam", 0) If @error Or $aRet[0] < 1  Then DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProcess) Exit EndIf $iCount = $aRet[0] - 1 $aRet = DllCall($iDLLKrnl32, "ptr", "VirtualAllocEx", "ptr", $hProcess, "ptr", 0, "ulong_ptr", _   $iTBBUTTON, "dword", BitOR($MEM_RESERVE, $MEM_COMMIT), "dword", $PAGE_READWRITE) If @error Or $aRet[0] = 0 Then DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProcess) Exit EndIf $pAddress = $aRet[0] GUICreate("Notification Icons", 600, 600) GUISetBkColor(0x494949) Global $hListView = GUICtrlCreateListView("", 2, 2, 596, 596) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES)) Global $hImage = _GUIImageList_Create(16,16,5,5) _GUICtrlListView_SetImageList($hListView, $hImage, 1) _GUICtrlListView_AddColumn($hListView, "Tray", 38) _GUICtrlListView_AddColumn($hListView, "Proc", 38) _GUICtrlListView_AddColumn($hListView, "Process", 138) _GUICtrlListView_AddColumn($hListView, "Module", 138) _GUICtrlListView_SetColumnWidth($hListView, 3, $LVSCW_AUTOSIZE_USEHEADER) GUISetState() For $iID = 0 To $iCount If IsHWnd($hToolbar) = False Then ExitLoop $aRet = DllCall($iDLLUser32, "lparam", "SendMessageW", "hwnd", $hToolbar, _    "int", $TB_GETBUTTON, "wparam", $iID, "lparam", $pAddress) If @error Or $aRet[0] <> 1 Then ContinueLoop $aRet = DllCall($iDLLKrnl32, "int", "ReadProcessMemory", "ptr", $hProcess, _    "ptr", $pAddress, "ptr", $pTBBUTTON, "ulong_ptr", $iTBBUTTON, "ulong_ptr*", -1) If @error Or $aRet[5] <> $iTBBUTTON Then ContinueLoop ;If BitAND(DllStructGetData($tTBBUTTON, "State"), $TBSTATE_HIDDEN) = $TBSTATE_HIDDEN Then ContinueLoop $aRet = DllCall($iDLLKrnl32, "int", "ReadProcessMemory", "ptr", $hProcess, _    "dword_ptr", DllStructGetData($tTBBUTTON, "Param"), "ptr", $pTRAYDATA, "ulong_ptr", $iTRAYDATA, "ulong_ptr*", -1) If @error Or $aRet[5] <> $iTRAYDATA Then ContinueLoop $hOwnerWin = DllStructGetData($tTRAYDATA, 1) If @error Or $hOwnerWin = 0 Then ContinueLoop $iPID = WinGetProcess($hOwnerWin) If @error Or $iPID = -1 Then ContinueLoop $hIconTray = DllStructGetData($tTRAYDATA, 5) ;returned icon handles shared $sRet = "" If Not _IsIconHandle($hIconTray, $sRet) Then   ;ConsoleWrite('!VarGetType($hIconTray) = ' & VarGetType($hIconTray) & @CRLF)   If IsPtr($hIconTray) Then $hIconTray = _WinAPI_Create32BitHICON($hIconTray)   ;some icons like HDDLife's temp icons return an invalid icon handle, and won't display, but will when formatted by _WinAPI_Create32BitHICON   If Not _IsIconHandle($hIconTray, $sRet) Then    $hIconTray = _GetTrayIconHandle($hOwnerWin)    ConsoleWrite("- Invalid Icon handle: OwnerWin: " & _WinAPI_GetClassName($hOwnerWin) &  "  Process Name: " & _ProcessGetName($iPID) & @crlf)   EndIf EndIf ;$hIconTray = _WinAPI_CopyImage($hIconTray, $IMAGE_ICON, 16, 16) _GUIImageList_ReplaceIcon($hImage, -1, $hIconTray) $hIcon = _WinAPI_ShellExtractAssociatedIcon(_WinAPI_GetProcessFileName($iPID), 1) $iImg = _GUIImageList_ReplaceIcon($hImage, -1, $hIcon) _GUICtrlListView_InsertItem($hListView, "", -1, $iImg-1) _GUICtrlListView_AddSubItem($hListView, $iIdx, "", 1, $iImg) _GUICtrlListView_AddSubItem($hListView, $iIdx, _ProcessGetName($iPID), 2) If $sRet = "" Then $sRet = _WinAPI_GetProcessFileName($iPID) _GUICtrlListView_AddSubItem($hListView, $iIdx, $sRet, 3) $iIdx += 1 ;ToolTip(_WinAPI_GetClassName($hOwnerWin), 1030, 850, $sRet, $hIconTray, 5) ;Sleep(500) _WinAPI_DestroyIcon($hIcon) _WinAPI_DestroyIcon($hIconTray) ;does not destroy traydata handles Next DllCall($iDLLKrnl32, "int", "VirtualFreeEx", "ptr", $hProcess, "ptr", $pAddress, "ulong_ptr", 0, "dword", $MEM_RELEASE) DllCall($iDLLKrnl32, "int", "CloseHandle", "ptr", $hProcess) DllClose($iDLLUser32) DllClose($iDLLKrnl32) ToolTip("") While GUIGetMsg() <> -3 WEnd _GUIImageList_Destroy($hImage) Exit Func _GetTrayIconHandle($hWnd, $hDLLUser32 = "User32.dll") If Not IsHWnd($hWnd) Then Return SetError(1, 1, -1) Local $iPID, $ParentPID, $aWinList $hIcon = _GetIcon($hWnd, $hDLLUser32) If Not @error And $hIcon <> -1 Then Return SetError(0, 0, $hIcon) $ParentPID = WinGetProcess($hWnd) If @error Or $ParentPID = -1 Then Return SetError(2, 2, -1) $aWinList = WinList() For $i = 1 to $aWinList[0][0]   $iPID = WinGetProcess($aWinList[$i][1])   If @error Or $iPID = -1 Then ContinueLoop   If $iPID = $ParentPID Then    $hIcon = _GetIcon($aWinList[$i][1], $hDLLUser32)    If Not @error And $hIcon <> -1 Then Return SetError(0, 0, $hIcon)   EndIf Next Return SetError(2, 2, -1) EndFunc ;modified from ModernMenu Win2Tray - by Holger Kotsch Func _GetIcon(ByRef $hWnd, $hDLLUser32 = "User32.dll") If Not IsHWnd($hWnd) Then Return SetError(1, 1, -1) Local Const $GCL_HICON = -14 Local Const $GCL_HICONSM = -34 Local $hIcon $hIcon = _SendMessage($hWnd, $WM_GETICON, 2, 0) If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon)) $hIcon = _SendMessage($hWnd, $WM_GETICON, 0, 0) If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon)) $hIcon = _WinAPI_GetClassLongEx($hWnd, $GCL_HICONSM) If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon)) $hIcon = _WinAPI_GetClassLongEx($hWnd, $GCL_HICON) If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon)) Return SetError(2, 2, -1) EndFunc Func _IsIconHandle($hIcon, ByRef $sMod) ;rover 2k11 Local $aRet Switch @OSVersion   Case "WIN_2008R2", "WIN_7", "WIN_2008", "WIN_VISTA"    $aRet = _WinAPI_GetIconInfoEx($hIcon)    If @error Then Return SetError(1, 1, False)    DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", $aRet[3])    DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", $aRet[4])    If $aRet[0] = 0 Then Return SetError(2, 2, False)    $sMod = $aRet[6]    Return SetError(0, 0, True)   Case "WIN_2003", "WIN_XP"    Local $tIconInfo = DllStructCreate("int fIcon;int xHotspot;int yHotspot;ptr hbmMask;ptr hbmColor")    Local $aRet = DllCall("User32.dll", "int", "GetIconInfo", "ptr", $hIcon, "ptr", DllStructGetPtr($tIconInfo))    If @error Or UBound($aRet) <> 3 Or $aRet[0] = 0 Then Return SetError(1, 1, False)    DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", DllStructGetData($tIconInfo, 4))    DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", DllStructGetData($tIconInfo, 5))    If Not DllStructGetData($tIconInfo, 1) Then Return SetError(2, 2, False)    Return SetError(0, 0, True) EndSwitch EndFunc

  • Zedna, UEZ, KaFu and 1 other like this
I see fascists...

#6 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,402 posts

Posted 20 December 2011 - 01:36 PM

Wuuhhaaa ;)... exactly what I was looking for :)!

I saw the shared memory technics in the SysTray UDF, but was not sure if this can be used (and more importantly how :)) to fetch the underlying icons. Of course there are always programs acting differently then others, not returning a valid handle. For those I'll add a fallback the parent Window Icon.

Thanks a bunch for the great example!

Enjoy your Christmas season ;)...

Edit:
"For those I'll add a fallback the parent Window Icon."... Which you've already added ;), saw this one later.

Edit 2:
I just noticed that actually I've read that post on xtremevbtalk.com before on my search for a solution! I just couldn't make any working AutoIt translation of it :D ...

Edited by KaFu, 20 December 2011 - 07:12 PM.


#7 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,402 posts

Posted 23 December 2011 - 02:38 PM

Hi Rover, can get it to work on Win7 :) . I'll keep on trying and will post when I suceed, but maybe you're seeing the issue quicker than I do. What I've already noticed is that the statement "Switch $iTbar" is always false as $iTbar is 0 in all cases.

#8 UEZ

UEZ

    Never say never

  • MVPs
  • 4,973 posts

Posted 23 December 2011 - 05:49 PM

The excellent script from rover is running properly only on my Win7 x64 system when I run it as x64 code using #AutoIt3Wrapper_UseX64=y.

Otherwise the list is empy!


Br,
UEZ

 
The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯


#9 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,402 posts

Posted 23 December 2011 - 07:14 PM

Now that's a good observation I hadn't thought about :). I'm also running on Win7-64 bit. On the other hand the _Systray UDF (first post) uses the same technique to access the explorer.exe data and it works fine running as 32bit. But maybe the problem is not related to the technique as such, but to the data to be extracted (structures wrong?).

Edited by KaFu, 23 December 2011 - 07:15 PM.


#10 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,402 posts

Posted 25 December 2011 - 10:05 AM

The problem was related to x86 <> x64 structure definitions :). UEZ, thanks for pointing the direction!

Merry Christmas to everyone!

AutoIt         
#NoTrayIcon #region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** ; <a href='http://www.autoitscript.com/forum/topic/134538-get-systray-icons-solved/page__view__findpost__p__948301' class='bbc_url' title=''>http://www.autoitscript.com/forum/topic/134538-get-systray-icons-solved/page__view__findpost__p__948301</a> ; coded by rover 2k11 #include <..WinAPIEx_3.5SMF_Func_WinAPIEx__v3.5_Beta.au3> #include <WinAPI.au3> #include <Process.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include <Constants.au3> #include <..WinAPIEx_3.5SMF_Func_WinAPIEx__v3.5_Beta_APIConstants.au3> #include <WindowsConstants.au3> #include <ToolBarConstants.au3> #include <ProcessConstants.au3> #include <MemoryConstants.au3> Opt("MustDeclareVars", 1) Global Const $PROCESS_ACCESS = BitOR($PROCESS_VM_OPERATION, $PROCESS_VM_READ) Global $hOwnerWin, $hTrayWnd, $hTrayNotifyWnd, $hSysPager, $hToolbar, _         $iDLLUser32 = DllOpen("user32.dll"), $iDLLKrnl32 = DllOpen("kernel32.dll"), _         $tTBBUTTON, $pTBBUTTON, $iTBBUTTON, $tTRAYDATA, $pTRAYDATA, $iTRAYDATA, _         $iImg = 0, $iIdx = 0, $iCount, $iPIDExp, $hProcess, $pAddress, $iPID, $aRet, $sRet, $hIconTray, $hIcon $hTrayWnd = WinGetHandle("[CLASS:Shell_TrayWnd]") $hTrayNotifyWnd = ControlGetHandle($hTrayWnd, "", "[CLASS:TrayNotifyWnd]") $hSysPager = ControlGetHandle($hTrayNotifyWnd, "", "[CLASS:SysPager]") $hToolbar = ControlGetHandle($hSysPager, "", "[CLASS:ToolbarWindow32; INSTANCE:1]") ; User Promoted Notification Area/Notification Area/SysTray Global $taglocalTBBUTTON If @OSArch = "X86" Then     $taglocalTBBUTTON = "int iBitmap;int idCommand;byte fsState;byte fsStyle;byte bReserved[2];dword_ptr dwData;int_ptr iString" Else ; X64     $taglocalTBBUTTON = "int iBitmap;int idCommand;byte fsState;byte fsStyle;byte bReserved[6];dword_ptr dwData;int_ptr iString" EndIf $tTBBUTTON = DllStructCreate($taglocalTBBUTTON) $pTBBUTTON = DllStructGetPtr($tTBBUTTON) $iTBBUTTON = DllStructGetSize($tTBBUTTON) If @OSArch = "X86" Then     $tTRAYDATA = DllStructCreate("hwnd hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];hwnd hIcon") Else     $tTRAYDATA = DllStructCreate("int64 hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];int64 hIcon") EndIf $pTRAYDATA = DllStructGetPtr($tTRAYDATA) $iTRAYDATA = DllStructGetSize($tTRAYDATA) ConsoleWrite("$iTRAYDATA " & $iTRAYDATA & @CRLF) $iPIDExp = WinGetProcess($hToolbar) If @error Or $iPIDExp = -1 Then Exit $aRet = DllCall($iDLLKrnl32, "ptr", "OpenProcess", "dword", _         $PROCESS_ACCESS, "int", 0, "int", $iPIDExp) If @error Or $aRet[0] = 0 Then Exit $hProcess = $aRet[0] $aRet = DllCall($iDLLUser32, "lparam", "SendMessageW", "hwnd", _         $hToolbar, "int", $TB_BUTTONCOUNT, "wparam", 0, "lparam", 0) If @error Or $aRet[0] < 1 Then     DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProcess)     Exit EndIf $iCount = $aRet[0] - 1 $aRet = DllCall($iDLLKrnl32, "ptr", "VirtualAllocEx", "ptr", $hProcess, "ptr", 0, "ulong_ptr", _         $iTBBUTTON, "dword", BitOR($MEM_RESERVE, $MEM_COMMIT), "dword", $PAGE_READWRITE) If @error Or $aRet[0] = 0 Then     DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProcess)     Exit EndIf $pAddress = $aRet[0] GUICreate("Notification Icons", 600, 600) GUISetBkColor(0x494949) Global $hListView = GUICtrlCreateListView("", 2, 2, 596, 596) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES)) Global $hImage = _GUIImageList_Create(16, 16, 5, 5) _GUICtrlListView_SetImageList($hListView, $hImage, 1) _GUICtrlListView_AddColumn($hListView, "Tray", 38) _GUICtrlListView_AddColumn($hListView, "Proc", 38) _GUICtrlListView_AddColumn($hListView, "Process", 138) _GUICtrlListView_AddColumn($hListView, "Module", 138) _GUICtrlListView_SetColumnWidth($hListView, 3, $LVSCW_AUTOSIZE_USEHEADER) GUISetState() For $iID = 0 To $iCount     If IsHWnd($hToolbar) = False Then ExitLoop     $aRet = DllCall($iDLLUser32, "lparam", "SendMessageW", "hwnd", $hToolbar, _             "int", $TB_GETBUTTON, "wparam", $iID, "lparam", $pAddress)     If @error Or $aRet[0] <> 1 Then ContinueLoop     ConsoleWrite("Step 1" & @CRLF)     $aRet = DllCall($iDLLKrnl32, "int", "ReadProcessMemory", "ptr", $hProcess, _             "ptr", $pAddress, "ptr", $pTBBUTTON, "ulong", $iTBBUTTON, "ulong*", -1)     If @error Or $aRet[5] <> $iTBBUTTON Then ContinueLoop     ConsoleWrite("Step 2 " & $iTBBUTTON & @TAB & $aRet[5] & @CRLF)     ;If BitAND(DllStructGetData($tTBBUTTON, "State"), $TBSTATE_HIDDEN) = $TBSTATE_HIDDEN Then ContinueLoop     ConsoleWrite($hProcess & @tab & ptr(DllStructGetData($tTBBUTTON, "Param")) & @tab & $pTRAYDATA & @tab & $iTRAYDATA & @crlf)     $aRet = DllCall($iDLLKrnl32, "int", "ReadProcessMemory", "ptr", $hProcess, _             "ptr", ptr(DllStructGetData($tTBBUTTON, 6)), "ptr", $pTRAYDATA, "ulong", $iTRAYDATA, "ulong*", 0)     ConsoleWrite("Step 3 " & $aRet[5] & @tab & $iTRAYDATA &  @CRLF)     If @error Or $aRet[5] <> $iTRAYDATA Then ContinueLoop     $hOwnerWin = DllStructGetData($tTRAYDATA, 1)     If @error Or $hOwnerWin = 0 Then ContinueLoop     ConsoleWrite("Step 4 " & $hOwnerWin & @CRLF)     $iPID = WinGetProcess(HWnd($hOwnerWin))     If @error Or $iPID = -1 Then ContinueLoop     ConsoleWrite("Step 5" & @CRLF)     $hIconTray = DllStructGetData($tTRAYDATA, 5) ;returned icon handles shared     $sRet = ""     If Not _IsIconHandle($hIconTray, $sRet) Then         ;ConsoleWrite('!VarGetType($hIconTray) = ' & VarGetType($hIconTray) & @CRLF)         If IsPtr($hIconTray) Then $hIconTray = _WinAPI_Create32BitHICON($hIconTray)         ;some icons like HDDLife's temp icons return an invalid icon handle, and won't display, but will when formatted by _WinAPI_Create32BitHICON         If Not _IsIconHandle($hIconTray, $sRet) Then             $hIconTray = _GetTrayIconHandle($hOwnerWin)             ConsoleWrite("- Invalid Icon handle: OwnerWin: " & _WinAPI_GetClassName($hOwnerWin) & "  Process Name: " & _ProcessGetName($iPID) & @CRLF)         EndIf     EndIf     ;$hIconTray = _WinAPI_CopyImage($hIconTray, $IMAGE_ICON, 16, 16)     _GUIImageList_ReplaceIcon($hImage, -1, $hIconTray)     $hIcon = _WinAPI_ShellExtractAssociatedIcon(_WinAPI_GetProcessFileName($iPID), 1)     $iImg = _GUIImageList_ReplaceIcon($hImage, -1, $hIcon)     _GUICtrlListView_InsertItem($hListView, "", -1, $iImg - 1)     _GUICtrlListView_AddSubItem($hListView, $iIdx, "", 1, $iImg)     _GUICtrlListView_AddSubItem($hListView, $iIdx, _ProcessGetName($iPID), 2)     If $sRet = "" Then $sRet = _WinAPI_GetProcessFileName($iPID)     _GUICtrlListView_AddSubItem($hListView, $iIdx, $sRet, 3)     $iIdx += 1     ;ToolTip(_WinAPI_GetClassName($hOwnerWin), 1030, 850, $sRet, $hIconTray, 5)     ;Sleep(500)     _WinAPI_DestroyIcon($hIcon)     _WinAPI_DestroyIcon($hIconTray) ;does not destroy traydata handles Next DllCall($iDLLKrnl32, "int", "VirtualFreeEx", "ptr", $hProcess, "ptr", $pAddress, "ulong_ptr", 0, "dword", $MEM_RELEASE) DllCall($iDLLKrnl32, "int", "CloseHandle", "ptr", $hProcess) DllClose($iDLLUser32) DllClose($iDLLKrnl32) ToolTip("") While GUIGetMsg() <> -3 WEnd _GUIImageList_Destroy($hImage) Exit Func _GetTrayIconHandle($hWnd, $hDLLUser32 = "User32.dll")     If Not IsHWnd($hWnd) Then Return SetError(1, 1, -1)     Local $iPID, $ParentPID, $aWinList     $hIcon = _GetIcon($hWnd, $hDLLUser32)     If Not @error And $hIcon <> -1 Then Return SetError(0, 0, $hIcon)     $ParentPID = WinGetProcess($hWnd)     If @error Or $ParentPID = -1 Then Return SetError(2, 2, -1)     $aWinList = WinList()     For $i = 1 To $aWinList[0][0]         $iPID = WinGetProcess($aWinList[$i][1])         If @error Or $iPID = -1 Then ContinueLoop         If $iPID = $ParentPID Then             $hIcon = _GetIcon($aWinList[$i][1], $hDLLUser32)             If Not @error And $hIcon <> -1 Then Return SetError(0, 0, $hIcon)         EndIf     Next     Return SetError(2, 2, -1) EndFunc   ;==>_GetTrayIconHandle ;modified from ModernMenu Win2Tray - by Holger Kotsch Func _GetIcon(ByRef $hWnd, $hDLLUser32 = "User32.dll")     If Not IsHWnd($hWnd) Then Return SetError(1, 1, -1)     Local Const $GCL_HICON = -14     Local Const $GCL_HICONSM = -34     Local $hIcon     $hIcon = _SendMessage($hWnd, $WM_GETICON, 2, 0)     If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon))     $hIcon = _SendMessage($hWnd, $WM_GETICON, 0, 0)     If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon))     $hIcon = _WinAPI_GetClassLongEx($hWnd, $GCL_HICONSM)     If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon))     $hIcon = _WinAPI_GetClassLongEx($hWnd, $GCL_HICON)     If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon))     Return SetError(2, 2, -1) EndFunc   ;==>_GetIcon Func _IsIconHandle($hIcon, ByRef $sMod)     ;rover 2k11     Local $aRet     Switch @OSVersion         Case "WIN_2008R2", "WIN_7", "WIN_2008", "WIN_VISTA"             $aRet = _WinAPI_GetIconInfoEx($hIcon)             If @error Then Return SetError(1, 1, False)             DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", $aRet[3])             DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", $aRet[4])             If $aRet[0] = 0 Then Return SetError(2, 2, False)             $sMod = $aRet[6]             Return SetError(0, 0, True)         Case "WIN_2003", "WIN_XP"             Local $tIconInfo = DllStructCreate("int fIcon;int xHotspot;int yHotspot;ptr hbmMask;ptr hbmColor")             Local $aRet = DllCall("User32.dll", "int", "GetIconInfo", "ptr", $hIcon, "ptr", DllStructGetPtr($tIconInfo))             If @error Or UBound($aRet) <> 3 Or $aRet[0] = 0 Then Return SetError(1, 1, False)             DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", DllStructGetData($tIconInfo, 4))             DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", DllStructGetData($tIconInfo, 5))             If Not DllStructGetData($tIconInfo, 1) Then Return SetError(2, 2, False)             Return SetError(0, 0, True)     EndSwitch EndFunc   ;==>_IsIconHandle


#11 rover

rover

    unmutual

  • Active Members
  • PipPipPipPipPipPip
  • 825 posts

Posted 25 January 2012 - 10:48 AM

Hi guys

My 64 bit mobo died, then I was away over the holidays,
so no testing for some time until i replaced it.

I changed the struct code to what KaFu posted, but it didn't work at first until I copied the entire post and saw that you convert the 64bit pointers (int64)
from the struct to 32bit with Hwnd() and Ptr() because they would otherwise be 32bit in a 32 bit process with ptr/hwnd and the explorer memory is 64bit. :)
nice fix guys
I see fascists...




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users