Jump to content

Systray_UDF Problem


apollo13
 Share

Recommended Posts

Well, I get a similar error when I use the provided WinAPIEx_3.8_3361 (like it says used for AutoIt v3.3.6.1).

But what I got installed is AutoIt v3.3.8.1 and WinAPIEx_3.8_3380, and then the script should run out of the box.

Edit:

Here's a compiled version.

_RefreshNotificationAreaIcons_x64.zip

What I realized is that it needs to be compiled in line with the OS architecture (x64). Had similar problems with HMW first too, the dll structures are not quite right. I have to compare this example to my own program, but in general it should be possible to create a x86 version which should run on x64 systems too (though the example provided above does not yet).

Edited by KaFu
Link to comment
Share on other sites

Here's the self-contained function to hide Systray icons properly. Tested on XP and Win7, you can compile it as x86 and it still should work on x64 systems too (well, at least it works for me :lol:).

Wraithdu's excellent is required for the identification & enumeration part. Example will hide all Systray icons, sleep 3 seconds and show them all again... test on your own risk :)...

#include <_SysTray.au3>
#include <Process.au3>

Local $count = _SysTrayIconCount()

For $i = $count - 1 To 0 Step -1
    $handle = _SysTrayIconHandle($i)
    $pid = WinGetProcess($handle)
    $name = _ProcessGetName($pid)
    _SysTray_HideIcon($i, 1)
Next

Sleep(3000)

For $i = $count - 1 To 0 Step -1
    $handle = _SysTrayIconHandle($i)
    $pid = WinGetProcess($handle)
    $name = _ProcessGetName($pid)
    _SysTray_HideIcon($i, 0)
Next

Func _SysTray_HideIcon($iID, $iHide = 0)
    Local $aRet

    Local Const $MEM_COMMIT = 0x00001000
    Local Const $MEM_RESERVE = 0x00002000
    Local Const $MEM_RELEASE = 0x00008000
    Local Const $PAGE_READWRITE = 0x4
    Local Const $TB_GETBUTTON = 0x0417

    Local $_hTrayWnd = WinGetHandle("[CLASS:Shell_TrayWnd]")
    Local $_hTrayNotifyWnd = ControlGetHandle($_hTrayWnd, "", "[CLASS:TrayNotifyWnd]")
    Local $_hSysPager = ControlGetHandle($_hTrayNotifyWnd, "", "[CLASS:SysPager]")
    Local $_hToolbar = ControlGetHandle($_hSysPager, "", "[CLASS:ToolbarWindow32; INSTANCE:1]") ; User Promoted Notification Area/Notification Area/SysTray

    Local $hWnd = DllCall("user32.dll", "hwnd", "FindWindow", "str", "NotifyIconOverflowWindow", "ptr", 0)
    Local $_hWnd_NotifyIconOverflowWindow = DllCall("user32.dll", "hwnd", "FindWindowEx", "hwnd", $hWnd[0], "hwnd", 0, "str", "ToolbarWindow32", "ptr", 0)

    Local $_GetIcon_tTBBUTTON
    If @OSArch = "X86" Then
        $_GetIcon_tTBBUTTON = DllStructCreate("int iBitmap;int idCommand;byte fsState;byte fsStyle;byte bReserved[2];dword_ptr dwData;int_ptr iString")
    Else ; X64
        $_GetIcon_tTBBUTTON = DllStructCreate("int iBitmap;int idCommand;byte fsState;byte fsStyle;byte bReserved[6];dword_ptr dwData;int_ptr iString")
    EndIf
    Local $_GetIcon_pTBBUTTON = DllStructGetPtr($_GetIcon_tTBBUTTON)
    Local $_GetIcon_iTBBUTTON = DllStructGetSize($_GetIcon_tTBBUTTON)

    Local $_GetIcon_tTRAYDATA
    If @OSArch = "X86" Then
        $_GetIcon_tTRAYDATA = DllStructCreate("hwnd hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];hwnd hIcon")
    Else
        $_GetIcon_tTRAYDATA = DllStructCreate("int64 hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];int64 hIcon")
    EndIf
    Local $_GetIcon_pTRAYDATA = DllStructGetPtr($_GetIcon_tTRAYDATA)
    Local $_GetIcon_iTRAYDATA = DllStructGetSize($_GetIcon_tTRAYDATA)

    Local $iPIDExp = WinGetProcess($_hToolbar)
    If @error Or $iPIDExp = -1 Then Exit 33

    $aRet = DllCall("kernel32.dll", "ptr", "OpenProcess", "dword", BitOR(0x0008, 0x0010, 0x0400), "int", 0, "int", $iPIDExp)
    If @error Or $aRet[0] = 0 Then Exit
    Local $_hProcess = $aRet[0]
    $aRet = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", "ptr", $_hProcess, "ptr", 0, "ulong_ptr", $_GetIcon_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 34 & $aRet[0]
    EndIf
    $_GetIcon_pAddress = $aRet[0]

    If IsHWnd($_hToolbar) = False Then Return -1
    $aRet = DllCall("user32.dll", "lparam", "SendMessageW", "hwnd", $_hToolbar, "int", $TB_GETBUTTON, "wparam", $iID, "lparam", $_GetIcon_pAddress)
    If @error Or $aRet[0] <> 1 Then Return -1

    $aRet = DllCall("kernel32.dll", "int", "ReadProcessMemory", "ptr", $_hProcess, "ptr", $_GetIcon_pAddress, "ptr", $_GetIcon_pTBBUTTON, "ulong", $_GetIcon_iTBBUTTON, "ulong*", -1)
    If @error Or $aRet[5] <> $_GetIcon_iTBBUTTON Then Return -1

    $aRet = DllCall("kernel32.dll", "int", "ReadProcessMemory", "ptr", $_hProcess, "ptr", Ptr(DllStructGetData($_GetIcon_tTBBUTTON, 6)), "ptr", $_GetIcon_pTRAYDATA, "ulong", $_GetIcon_iTRAYDATA, "ulong*", -1)
    If @error Or $aRet[5] <> $_GetIcon_iTRAYDATA Then Return -1

    $_hOwnerWin = HWnd(DllStructGetData($_GetIcon_tTRAYDATA, 1))
    If @error Or $_hOwnerWin = 0 Then Return -1

    Local $iPID = WinGetProcess($_hOwnerWin)
    If @error Or $iPID = -1 Then Return -1

    Local $tNOTIFYICONDATA = DllStructCreate("dword;hwnd;uint;uint;uint;ptr;wchar[128];dword;dword;wchar[256];uint;wchar[64];dword;int;short;short;byte[8];ptr")
    Local $pNOTIFYICONDATA = DllStructGetPtr($tNOTIFYICONDATA)
    DllStructSetData($tNOTIFYICONDATA, 1, DllStructGetSize($tNOTIFYICONDATA))
    DllStructSetData($tNOTIFYICONDATA, 2, $_hOwnerWin)
    DllStructSetData($tNOTIFYICONDATA, 3, DllStructGetData($_GetIcon_tTRAYDATA, 2))

    DllStructSetData($tNOTIFYICONDATA, 4, 0x8) ; NIF_STATE (0x00000008)
    If $iHide Then
        DllStructSetData($tNOTIFYICONDATA, 8, 0x1) ; dwState = NIS_HIDDEN (0x00000001)
    Else
        DllStructSetData($tNOTIFYICONDATA, 8, 0x0)
    EndIf
    DllStructSetData($tNOTIFYICONDATA, 9, 0x1) ; dwStateMask


    $aRet = DllCall("user32.dll", "int", "SendMessageW", "hwnd", $_hToolbar, "uint", 1028, "wparam", DllStructGetData($_GetIcon_tTBBUTTON, 2), "lparam", $iHide)

    $aRet = DllCall("shell32.dll", "int", "Shell_NotifyIconW", "dword", 0x1, "ptr", $pNOTIFYICONDATA) ; NIM_MODIFY (0x00000001)
    If Not IsHWnd($_hWnd_NotifyIconOverflowWindow) Then DllCall("user32.dll", "int", "SendMessageW", "hwnd", $_hTrayWnd, "uint", 0x001A, "wparam", 0, "lparam", 0) ; WM_SETTINGCHANGE 0x001A ; for Update on XP

    DllCall("kernel32.dll", "int", "VirtualFreeEx", "ptr", $_hProcess, "ptr", $_GetIcon_pAddress, "ulong_ptr", 0, "dword", $MEM_RELEASE)
    DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $_hProcess)

EndFunc   ;==>_SysTray_HideIcon
Edited by KaFu
Link to comment
Share on other sites

Thank you, i have downloaded new version WinAPIEx and error of "DuplicateHandle" are solved

but my problem persists as running your script compiled.

I have compiled the same on x86 and x64 but nothing to do.

If you run a script that starts program "TEST.exe" and script removes its systray icon and using

your applications you must close and open again same script "TIME.exe" and

starts and close again more times the same program "TEST.exe" and remove again same icon...

..systray area dimension crazy and all programs that you have counciled me don't take effect.

Don't solve my problem, and in this condition if you run "TASKMANAGER" in order to see

"CPU % used" the graphic icon are not showed in notification area.

I have lose hope to solve. :-(

Link to comment
Share on other sites

Well, the function _SysTray_HideIcon() in post #22 definitely removes an icon from the Systray on XP and Win7 for me cleanly, and additionally on Win7 it also does not leave a blank space behind. I've also implemented it into my program HMW and I'm currently satisfied with it's behavior.

Of course if you re-start a program in your script by e.g. calling it run(), you have to re-remove the corresponding Systray Icon each time. If this still fails, either post or PM your full code...

#NoTrayIcon
#include <_SysTray.au3>

Func _Run_and_SysTray_HideIcon($sProgram, $sWorkingDir, $iShowFlag, $iOptFlag, $iTimeout = 10000)
    $iPID = Run($sProgram, $sWorkingDir, $iShowFlag, $iOptFlag)
    If @error Then Return SetError(1) ; run failed
    Local $Tray_Count, $Tray_Handle, $Tray_PID
    Local $timer = TimerInit()
    While 1
        If TimerDiff($timer) > $iTimeout Then Return SetError(2) ; timeout
        Sleep(100)
        $Tray_Count = _SysTrayIconCount()
        For $i = $Tray_Count - 1 To 0 Step -1
            $Tray_Handle = _SysTrayIconHandle($i)
            $Tray_PID = WinGetProcess($Tray_Handle)
            If $Tray_PID = $iPID Then ; of course this assumes the pid returned by run() is the same that creates the systray icon, might fail if the program spawns a child pid, then use _ProcessGetName() to identify string
                _SysTray_HideIcon($i, 1)
                Return 1 ; success
            EndIf
        Next
    WEnd
EndFunc   ;==>_Run_and_SysTray_HideIcon

Func _SysTray_HideIcon($iID, $iHide = 0)
    Local $aRet

    Local Const $MEM_COMMIT = 0x00001000
    Local Const $MEM_RESERVE = 0x00002000
    Local Const $MEM_RELEASE = 0x00008000
    Local Const $PAGE_READWRITE = 0x4
    Local Const $TB_GETBUTTON = 0x0417

    Local $_hTrayWnd = WinGetHandle("[CLASS:Shell_TrayWnd]")
    Local $_hTrayNotifyWnd = ControlGetHandle($_hTrayWnd, "", "[CLASS:TrayNotifyWnd]")
    Local $_hSysPager = ControlGetHandle($_hTrayNotifyWnd, "", "[CLASS:SysPager]")
    Local $_hToolbar = ControlGetHandle($_hSysPager, "", "[CLASS:ToolbarWindow32; INSTANCE:1]") ; User Promoted Notification Area/Notification Area/SysTray

    Local $hWnd = DllCall("user32.dll", "hwnd", "FindWindow", "str", "NotifyIconOverflowWindow", "ptr", 0)
    Local $_hWnd_NotifyIconOverflowWindow = DllCall("user32.dll", "hwnd", "FindWindowEx", "hwnd", $hWnd[0], "hwnd", 0, "str", "ToolbarWindow32", "ptr", 0)

    Local $_GetIcon_tTBBUTTON
    If @OSArch = "X86" Then
        $_GetIcon_tTBBUTTON = DllStructCreate("int iBitmap;int idCommand;byte fsState;byte fsStyle;byte bReserved[2];dword_ptr dwData;int_ptr iString")
    Else ; X64
        $_GetIcon_tTBBUTTON = DllStructCreate("int iBitmap;int idCommand;byte fsState;byte fsStyle;byte bReserved[6];dword_ptr dwData;int_ptr iString")
    EndIf
    Local $_GetIcon_pTBBUTTON = DllStructGetPtr($_GetIcon_tTBBUTTON)
    Local $_GetIcon_iTBBUTTON = DllStructGetSize($_GetIcon_tTBBUTTON)

    Local $_GetIcon_tTRAYDATA
    If @OSArch = "X86" Then
        $_GetIcon_tTRAYDATA = DllStructCreate("hwnd hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];hwnd hIcon")
    Else
        $_GetIcon_tTRAYDATA = DllStructCreate("int64 hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];int64 hIcon")
    EndIf
    Local $_GetIcon_pTRAYDATA = DllStructGetPtr($_GetIcon_tTRAYDATA)
    Local $_GetIcon_iTRAYDATA = DllStructGetSize($_GetIcon_tTRAYDATA)

    Local $iPIDExp = WinGetProcess($_hToolbar)
    If @error Or $iPIDExp = -1 Then Exit 33

    $aRet = DllCall("kernel32.dll", "ptr", "OpenProcess", "dword", BitOR(0x0008, 0x0010, 0x0400), "int", 0, "int", $iPIDExp)
    If @error Or $aRet[0] = 0 Then Exit
    Local $_hProcess = $aRet[0]
    $aRet = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", "ptr", $_hProcess, "ptr", 0, "ulong_ptr", $_GetIcon_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 34 & $aRet[0]
    EndIf
    $_GetIcon_pAddress = $aRet[0]

    If IsHWnd($_hToolbar) = False Then Return -1
    $aRet = DllCall("user32.dll", "lparam", "SendMessageW", "hwnd", $_hToolbar, "int", $TB_GETBUTTON, "wparam", $iID, "lparam", $_GetIcon_pAddress)
    If @error Or $aRet[0] <> 1 Then Return -1

    $aRet = DllCall("kernel32.dll", "int", "ReadProcessMemory", "ptr", $_hProcess, "ptr", $_GetIcon_pAddress, "ptr", $_GetIcon_pTBBUTTON, "ulong", $_GetIcon_iTBBUTTON, "ulong*", -1)
    If @error Or $aRet[5] <> $_GetIcon_iTBBUTTON Then Return -1

    $aRet = DllCall("kernel32.dll", "int", "ReadProcessMemory", "ptr", $_hProcess, "ptr", Ptr(DllStructGetData($_GetIcon_tTBBUTTON, 6)), "ptr", $_GetIcon_pTRAYDATA, "ulong", $_GetIcon_iTRAYDATA, "ulong*", -1)
    If @error Or $aRet[5] <> $_GetIcon_iTRAYDATA Then Return -1

    $_hOwnerWin = HWnd(DllStructGetData($_GetIcon_tTRAYDATA, 1))
    If @error Or $_hOwnerWin = 0 Then Return -1

    Local $iPID = WinGetProcess($_hOwnerWin)
    If @error Or $iPID = -1 Then Return -1

    Local $tNOTIFYICONDATA = DllStructCreate("dword;hwnd;uint;uint;uint;ptr;wchar[128];dword;dword;wchar[256];uint;wchar[64];dword;int;short;short;byte[8];ptr")
    Local $pNOTIFYICONDATA = DllStructGetPtr($tNOTIFYICONDATA)
    DllStructSetData($tNOTIFYICONDATA, 1, DllStructGetSize($tNOTIFYICONDATA))
    DllStructSetData($tNOTIFYICONDATA, 2, $_hOwnerWin)
    DllStructSetData($tNOTIFYICONDATA, 3, DllStructGetData($_GetIcon_tTRAYDATA, 2))

    DllStructSetData($tNOTIFYICONDATA, 4, 0x8) ; NIF_STATE (0x00000008)
    If $iHide Then
        DllStructSetData($tNOTIFYICONDATA, 8, 0x1) ; dwState = NIS_HIDDEN (0x00000001)
    Else
        DllStructSetData($tNOTIFYICONDATA, 8, 0x0)
    EndIf
    DllStructSetData($tNOTIFYICONDATA, 9, 0x1) ; dwStateMask


    $aRet = DllCall("user32.dll", "int", "SendMessageW", "hwnd", $_hToolbar, "uint", 1028, "wparam", DllStructGetData($_GetIcon_tTBBUTTON, 2), "lparam", $iHide)

    $aRet = DllCall("shell32.dll", "int", "Shell_NotifyIconW", "dword", 0x1, "ptr", $pNOTIFYICONDATA) ; NIM_MODIFY (0x00000001)
    If Not IsHWnd($_hWnd_NotifyIconOverflowWindow) Then DllCall("user32.dll", "int", "SendMessageW", "hwnd", $_hTrayWnd, "uint", 0x001A, "wparam", 0, "lparam", 0) ; WM_SETTINGCHANGE 0x001A ; for Update on XP

    DllCall("kernel32.dll", "int", "VirtualFreeEx", "ptr", $_hProcess, "ptr", $_GetIcon_pAddress, "ulong_ptr", 0, "dword", $MEM_RELEASE)
    DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $_hProcess)

EndFunc   ;==>_SysTray_HideIcon
Edited by KaFu
Link to comment
Share on other sites

I have found on WEB an application of 125KB :

Notification Area Cleaner for Windows Ver. 1.0.0.1 Author: Igor Tolmachev

and using this EXE all system area is cleaned correctly and dimension come back

to original dimension and there are no blank space near clock.

Unfortunately after using this EXE all icons that i have removed are showed again and in addiction this is not an invisible task to insert in all my script when i will want remove tray icon of my program.

In fact i must open file, wait and then click on "CLEAN". It stops "explorer.exe", send WM_Quiet messages to all explorer Windows, clean area, and at the end, Starts again Explorer.

It not work on background for this reason i can't use it also solve probem of SysTray Area.

Doing other infinite tests i have proved to remove in "systray_udf" the function

_SysTrayIconHide that using it, script causes always blank space near clock...

..and adding in the same position function your _SysTray_HideIcon()

In this mode i can't remove icon, but icon now is hide and don't cause wrong dimension of notification area and all programs

(also TaskManager) put correctly their Tray Icon in TrayArea.

Icons that i want are invisible, less space in TrayArea used, and all runs. :-))) Yeah!

I'm happy that i outflank my problem, also if I DON'T UNDERSTAND WHY

function "REMOVE" causes all problems and your function "Hide" none.

If i remove an icon Windows will angry but if i hide an icon all OK. :-/

"SysTray_UDF" has 2 bugs in the actual version with date 01/13/11 of Last Update.

-1) HideIcons don't run very well but replacing it with your script now all run

-2) RemoveIcons don't run

Thank you to you KaFu and thanks to all forum, that with your web link, councils, and different scripts

i have obtained what i'm looking for, also if using a different solution to "remove icon".

Best regards

Link to comment
Share on other sites

The reasons why the remove function from the original Systray UDF fails is the same as why the original hide function fails to remove the blank space. In the original UDF the icons were deleted from the toolbar, on XP that worked fine, on Win7 this leaves a blank space behind. After deleting the toolbar button, on Win7 it is necessary to delete the underlying icon itself with an API call of "Shell_NotifyIcon".

As for the _SysTray_HideIcon() example above, the _SysTray_RemoveIcon() example below is self-contained, the code around it is just to give an working example.

#include <.._Systray_SysTray.au3> ; for _SysTrayIconCount() only
#include <..WinAPIEx_3.8_3380APIConstants.au3> ; for creating test icons only
#include <..WinAPIEx_3.8_3380WinAPIEx.au3> ; for creating test icons only

Global $hWnd = WinGetHandle(AutoItWinGetTitle())
Global $tNOTIFYICONDATA = DllStructCreate($tagNOTIFYICONDATA)

OnAutoItExitRegister('OnAutoItExit')

DllStructSetData($tNOTIFYICONDATA, 'Size', DllStructGetSize($tNOTIFYICONDATA))
DllStructSetData($tNOTIFYICONDATA, 'hWnd', WinGetHandle(AutoItWinGetTitle()))
DllStructSetData($tNOTIFYICONDATA, 'Flags', $NIF_ICON)

DllStructSetData($tNOTIFYICONDATA, 'ID', 2)
DllStructSetData($tNOTIFYICONDATA, 'hIcon', _WinAPI_ShellExtractIcon(@SystemDir & 'shell32.dll', 166, 16, 16))
_WinAPI_ShellNotifyIcon($NIM_ADD, $tNOTIFYICONDATA)

DllStructSetData($tNOTIFYICONDATA, 'ID', 3)
DllStructSetData($tNOTIFYICONDATA, 'hIcon', _WinAPI_ShellExtractIcon(@SystemDir & 'shell32.dll', 130, 16, 16))
_WinAPI_ShellNotifyIcon($NIM_ADD, $tNOTIFYICONDATA)

DllStructSetData($tNOTIFYICONDATA, 'ID', 4)
DllStructSetData($tNOTIFYICONDATA, 'hIcon', _WinAPI_ShellExtractIcon(@SystemDir & 'shell32.dll', 131, 16, 16))
_WinAPI_ShellNotifyIcon($NIM_ADD, $tNOTIFYICONDATA)

DllStructSetData($tNOTIFYICONDATA, 'ID', 5)
DllStructSetData($tNOTIFYICONDATA, 'hIcon', _WinAPI_ShellExtractIcon(@SystemDir & 'shell32.dll', 132, 16, 16))
_WinAPI_ShellNotifyIcon($NIM_ADD, $tNOTIFYICONDATA)


TraySetToolTip("ToolTipTest")

For $y = 0 To 4
    Sleep(1000)
    Local $count = _SysTrayIconCount()
    For $i = $count - 1 To 0 Step -1
        $handle = _SysTrayIconHandle($i)
        $pid = WinGetProcess($handle)
        If $pid = @AutoItPID Then
            _SysTray_RemoveIcon($i)
            ExitLoop
        EndIf
    Next
Next

Exit



Func _SysTray_RemoveIcon($iID)
    Local $aRet

    Local Const $MEM_COMMIT = 0x00001000
    Local Const $MEM_RESERVE = 0x00002000
    Local Const $MEM_RELEASE = 0x00008000
    Local Const $PAGE_READWRITE = 0x4
    Local Const $TB_GETBUTTON = 0x0417

    Local $_hTrayWnd = WinGetHandle("[CLASS:Shell_TrayWnd]")
    Local $_hTrayNotifyWnd = ControlGetHandle($_hTrayWnd, "", "[CLASS:TrayNotifyWnd]")
    Local $_hSysPager = ControlGetHandle($_hTrayNotifyWnd, "", "[CLASS:SysPager]")
    Local $_hToolbar = ControlGetHandle($_hSysPager, "", "[CLASS:ToolbarWindow32; INSTANCE:1]") ; User Promoted Notification Area/Notification Area/SysTray

    Local $hWnd = DllCall("user32.dll", "hwnd", "FindWindow", "str", "NotifyIconOverflowWindow", "ptr", 0)
    Local $_hWnd_NotifyIconOverflowWindow = DllCall("user32.dll", "hwnd", "FindWindowEx", "hwnd", $hWnd[0], "hwnd", 0, "str", "ToolbarWindow32", "ptr", 0)

    Local $_GetIcon_tTBBUTTON
    If @OSArch = "X86" Then
        $_GetIcon_tTBBUTTON = DllStructCreate("int iBitmap;int idCommand;byte fsState;byte fsStyle;byte bReserved[2];dword_ptr dwData;int_ptr iString")
    Else ; X64
        $_GetIcon_tTBBUTTON = DllStructCreate("int iBitmap;int idCommand;byte fsState;byte fsStyle;byte bReserved[6];dword_ptr dwData;int_ptr iString")
    EndIf
    Local $_GetIcon_pTBBUTTON = DllStructGetPtr($_GetIcon_tTBBUTTON)
    Local $_GetIcon_iTBBUTTON = DllStructGetSize($_GetIcon_tTBBUTTON)

    Local $_GetIcon_tTRAYDATA
    If @OSArch = "X86" Then
        $_GetIcon_tTRAYDATA = DllStructCreate("hwnd hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];hwnd hIcon")
    Else
        $_GetIcon_tTRAYDATA = DllStructCreate("int64 hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];int64 hIcon")
    EndIf
    Local $_GetIcon_pTRAYDATA = DllStructGetPtr($_GetIcon_tTRAYDATA)
    Local $_GetIcon_iTRAYDATA = DllStructGetSize($_GetIcon_tTRAYDATA)

    Local $iPIDExp = WinGetProcess($_hToolbar)
    If @error Or $iPIDExp = -1 Then Exit 33

    $aRet = DllCall("kernel32.dll", "ptr", "OpenProcess", "dword", BitOR(0x0008, 0x0010, 0x0400), "int", 0, "int", $iPIDExp)
    If @error Or $aRet[0] = 0 Then Exit
    Local $_hProcess = $aRet[0]
    $aRet = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", "ptr", $_hProcess, "ptr", 0, "ulong_ptr", $_GetIcon_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 34 & $aRet[0]
    EndIf
    $_GetIcon_pAddress = $aRet[0]

    If IsHWnd($_hToolbar) = False Then Return -1
    $aRet = DllCall("user32.dll", "lparam", "SendMessageW", "hwnd", $_hToolbar, "int", $TB_GETBUTTON, "wparam", $iID, "lparam", $_GetIcon_pAddress)
    If @error Or $aRet[0] <> 1 Then Return -1

    $aRet = DllCall("kernel32.dll", "int", "ReadProcessMemory", "ptr", $_hProcess, "ptr", $_GetIcon_pAddress, "ptr", $_GetIcon_pTBBUTTON, "ulong", $_GetIcon_iTBBUTTON, "ulong*", -1)
    If @error Or $aRet[5] <> $_GetIcon_iTBBUTTON Then Return -1

    $aRet = DllCall("kernel32.dll", "int", "ReadProcessMemory", "ptr", $_hProcess, "ptr", Ptr(DllStructGetData($_GetIcon_tTBBUTTON, 6)), "ptr", $_GetIcon_pTRAYDATA, "ulong", $_GetIcon_iTRAYDATA, "ulong*", -1)
    If @error Or $aRet[5] <> $_GetIcon_iTRAYDATA Then Return -1

    $_hOwnerWin = HWnd(DllStructGetData($_GetIcon_tTRAYDATA, 1))
    If @error Or $_hOwnerWin = 0 Then Return -1

    Local $iPID = WinGetProcess($_hOwnerWin)
    If @error Or $iPID = -1 Then Return -1

    Local $tNOTIFYICONDATA = DllStructCreate("dword;hwnd;uint;uint;uint;ptr;wchar[128];dword;dword;wchar[256];uint;wchar[64];dword;int;short;short;byte[8];ptr")
    Local $pNOTIFYICONDATA = DllStructGetPtr($tNOTIFYICONDATA)
    DllStructSetData($tNOTIFYICONDATA, 1, DllStructGetSize($tNOTIFYICONDATA))
    DllStructSetData($tNOTIFYICONDATA, 2, $_hOwnerWin)
    DllStructSetData($tNOTIFYICONDATA, 3, DllStructGetData($_GetIcon_tTRAYDATA, 2))

    $aRet = DllCall("user32.dll", "int", "SendMessageW", "hwnd", $_hToolbar, "uint", 1028, "wparam", DllStructGetData($_GetIcon_tTBBUTTON, 2), "lparam", 1) ; Hide Button

    $aRet = DllCall("shell32.dll", "int", "Shell_NotifyIconW", "dword", 0x2, "ptr", $pNOTIFYICONDATA) ; NIM_DELETE (0x00000002)
    If Not IsHWnd($_hWnd_NotifyIconOverflowWindow) Then DllCall("user32.dll", "int", "SendMessageW", "hwnd", $_hTrayWnd, "uint", 0x001A, "wparam", 0, "lparam", 0) ; WM_SETTINGCHANGE 0x001A ; for Update on XP

    DllCall("kernel32.dll", "int", "VirtualFreeEx", "ptr", $_hProcess, "ptr", $_GetIcon_pAddress, "ulong_ptr", 0, "dword", $MEM_RELEASE)
    DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $_hProcess)

EndFunc   ;==>_SysTray_RemoveIcon

Func OnAutoItExit()
    DllStructSetData($tNOTIFYICONDATA, 'ID', 2)
    _WinAPI_ShellNotifyIcon($NIM_DELETE, $tNOTIFYICONDATA)
    DllStructSetData($tNOTIFYICONDATA, 'ID', 3)
    _WinAPI_ShellNotifyIcon($NIM_DELETE, $tNOTIFYICONDATA)
    DllStructSetData($tNOTIFYICONDATA, 'ID', 4)
    _WinAPI_ShellNotifyIcon($NIM_DELETE, $tNOTIFYICONDATA)
    DllStructSetData($tNOTIFYICONDATA, 'ID', 5)
    _WinAPI_ShellNotifyIcon($NIM_DELETE, $tNOTIFYICONDATA)
EndFunc   ;==>OnAutoItExit
Link to comment
Share on other sites

Thank you very much, but an information:

If i want replace in SystrayUDF also this function of RemoveIcon With your script as i have done with HideIcon

how i must put into UDF from your script ??

I have inserted only Function that starts

Func _SysTray_RemoveIcon($iID)

...

.......

EndFunc ;==>_SysTray_RemoveIcon

and running

#NoTrayIcon

#Include <systray_udf.au3>

_SysTrayIconRemove(_SysTrayIconIndex("Application.exe"))

causes error of variable.

Using function replace with your script

_SysTrayIconHide(_SysTrayIconIndex("Application.exe"))

all run very well

Need WinAPIEx for removing icon that In your script Hide is not used??

What is necessary add to have only the complete function?

Thanks

Link to comment
Share on other sites

Can't replicate your error. Maybe it's related to _SysTrayIconIndex()? Try to debug with something like this:

Local $i_SysTray_Index = _SysTrayIconIndex("Application.exe")
ConsoleWrite($i_SysTray_Index & @crlf)
_SysTrayIconHide($i_SysTray_Index)

Another way would be to use your own wrapper, something like this works fine for me (should work for process IDs and process names too):

Func _SysTray_HideIcon_Process($iPID_Target, $iHide = 1)
    $iPID_Target = ProcessExists($iPID_Target)
    If Not $iPID_Target Then Return SetError(1)
    Local $iCount = _SysTrayIconCount()
    For $i = $iCount - 1 To 0 Step -1
        If WinGetProcess(_SysTrayIconHandle($i)) = $iPID_Target Then _SysTray_HideIcon($i, $iHide)
    Next
EndFunc   ;==>_SysTray_HideIcon_Process

Func _SysTray_RemoveIcon_Process($iPID_Target)
    $iPID_Target = ProcessExists($iPID_Target)
    If Not $iPID_Target Then Return SetError(1)
    Local $iCount = _SysTrayIconCount()
    For $i = $iCount - 1 To 0 Step -1
        If WinGetProcess(_SysTrayIconHandle($i)) = $iPID_Target Then _SysTray_RemoveIcon($i)
    Next
EndFunc   ;==>_SysTray_RemoveIcon_Process

I've wrapped it all into an updated version of _SysTray.au3, APIConstants.au3 and WinAPIEx.au3 are only needed for the examples to work (to create some more systray icons to test).

_Systray.zip

Edited by KaFu
Link to comment
Share on other sites

You can't replicate my errors using SystrayIconHide because also me run very well this function.

The error are showed using Function SystrayIconRemove that i have inserted in SYSTRAY_udf replacing old

original function that remove icon.

Now I will prove adding _SysTray_RemoveIcon_Process

Thanks for your patience

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...