KaFu Posted November 5, 2011 Share Posted November 5, 2011 (edited) For my current Project (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 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 ? Edited December 20, 2011 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2022-Nov-26) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Feb-16) HMW - Hide my Windows (2018-Sep-16) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2023-Jun-03) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
KaFu Posted November 9, 2011 Author Share Posted November 9, 2011 Anyone ? OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2022-Nov-26) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Feb-16) HMW - Hide my Windows (2018-Sep-16) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2023-Jun-03) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
careca Posted November 9, 2011 Share Posted November 9, 2011 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. Spoiler Renamer - Rename files and folders, remove portions of text from the filename etc. GPO Tool - Export/Import Group policy settings. MirrorDir - Synchronize/Backup/Mirror Folders BeatsPlayer - Music player. Params Tool - Right click an exe to see it's parameters or execute them. String Trigger - Triggers pasting text or applications or internet links on specific strings. Inconspicuous - Hide files in plain sight, not fully encrypted. Regedit Control - Registry browsing history, quickly jump into any saved key. Time4Shutdown - Write the time for shutdown in minutes. Power Profiles Tool - Set a profile as active, delete, duplicate, export and import. Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes. NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s. IUIAutomation - Topic with framework and examples Au3Record.exe Link to comment Share on other sites More sharing options...
KaFu Posted November 9, 2011 Author Share Posted November 9, 2011 (edited) 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 ... Edited November 9, 2011 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2022-Nov-26) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Feb-16) HMW - Hide my Windows (2018-Sep-16) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2023-Jun-03) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
rover Posted December 20, 2011 Share Posted December 20, 2011 For my current Project (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 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 expandcollapse popup;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 Mat, Zedna, UEZ and 1 other 4 I see fascists... Link to comment Share on other sites More sharing options...
KaFu Posted December 20, 2011 Author Share Posted December 20, 2011 (edited) 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 ... Edited December 20, 2011 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2022-Nov-26) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Feb-16) HMW - Hide my Windows (2018-Sep-16) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2023-Jun-03) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
KaFu Posted December 23, 2011 Author Share Posted December 23, 2011 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. OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2022-Nov-26) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Feb-16) HMW - Hide my Windows (2018-Sep-16) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2023-Jun-03) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
UEZ Posted December 23, 2011 Share Posted December 23, 2011 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 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
KaFu Posted December 23, 2011 Author Share Posted December 23, 2011 (edited) 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 December 23, 2011 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2022-Nov-26) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Feb-16) HMW - Hide my Windows (2018-Sep-16) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2023-Jun-03) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
KaFu Posted December 25, 2011 Author Share Posted December 25, 2011 The problem was related to x86 <> x64 structure definitions . UEZ, thanks for pointing the direction! Merry Christmas to everyone! expandcollapse popup#NoTrayIcon #region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** ; http://www.autoitscript.com/forum/topic/134538-get-systray-icons-solved/page__view__findpost__p__948301 ; 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 OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2022-Nov-26) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Feb-16) HMW - Hide my Windows (2018-Sep-16) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2023-Jun-03) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
rover Posted January 25, 2012 Share Posted January 25, 2012 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... 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