Jump to content

_ToggleSystemTrayState with support for specific icons


Recommended Posts

I was helping another user the other day And decided To make a UDF so here it is. Let me know what ya think. ;)

#include-once
#include <GuiListView.au3>

Global Const $SW_HIDENA = 2, $SW_HIDENOACTIVE = 2

; Examples are below.

; #FUNCTION# ====================================================================================================================
; Name ..........: _ToggleSystemTrayState
; Description ...: Hide/Show System Tray Icons by Name or Set the State for all Icons
; Syntax ........: _ToggleSystemTrayState([$vTrayItems = ""[, $iStartSearchIndex = 0[, $iSystemTrayState = 0[, $iDebug = 0]]]])
; Parameters ....: $vTrayItems           - [optional] A variant value. Default is "".
;                $iStartSearchIndex - [optional] An integer value. Default is 0. Set this to -1 to search from end to start.
;                $iSystemTrayState - [optional] An integer value. Default is 0.
;                $iDebug             - [optional] An integer value. Default is 0. Set this to either @SW_SHOW or 1 to see dialogs and debug information.
; Return values .: None
; Author ........: Decipher
; Modified ......:
; Remarks .......: Tested only on XP
;
; $iSystemTrayState can be one of the following:
; @SW_SHOW == ALWAYS_SHOW == 5
; @SW_HIDE == ALWAYS_HIDE == 0
; $SW_HIDENA == HIDE WHEN INACTIVE == 2
;
; $vTrayItems can be a string for a specific icon or an array for multiple icons
; There is no error checking implemented but feel free to change it to your needs.
;
; Related .......:
; Link ..........:
; Example .......: Yes, The examples need to be uncommented to run. Remove the ( ;- ) prefix on the example to be ran.
; ===============================================================================================================================


    ;;;; Set all icons to hide when inactive. ;;;;
;-    _ToggleSystemTrayState($SW_HIDENA) ; Example #1

    ;;;; Hide all system tray icons. ;;;;
;-    _ToggleSystemTrayState(@SW_HIDE) ; Example #2

    ;;;; Show two specific icons. ;;;;
;-    Local $aIcons[2] = ["Local Area Connection", "Volume"] ; Example #3
;-    _ToggleSystemTrayState($aIcons, 0, @SW_SHOW)

    ;;;; Hide a specific icon. ;;;;
;-    _ToggleSystemTrayState("Volume", 0, @SW_HIDE) ; Example #4

    ;;;; Show all system tray icons. ;;;;
;-    _ToggleSystemTrayState(@SW_SHOW) ; Example #5

    ;;;; Hide all system tray icons but show the dialogs aka debug mode and log the names of the icons hidden. ;;;;
;-    _ToggleSystemTrayState("", 0, @SW_HIDE, 1) ; Example #6


Func _ToggleSystemTrayState($vTrayItems = "", $iStartSearchIndex = 0, $iSystemTrayState = 0, $iDebug = 0)
    If IsInt($vTrayItems) Then
        $iSystemTrayState = $vTrayItems
        $vTrayItems = ""
    EndIf
    Local Const $sOPTIONS_DIALOG_PROCESS = "rundll32.exe shell32.dll, Options_RunDLL 1"
    Local Const $sTASKBAR_PROPERTIES_TITLE = "[TITLE:Taskbar and Start Menu Properties; CLASS:#32770; INSTANCE:1]"
    Local Const $sCUSTOMIZE_BUTTON = "[ClassnameNN:Button10]", $sSENDKEYS = "!c"
    Local Const $sTASKBAR_CUSTOMIZE_TITLE = "[TITLE:Customize Notifications; CLASS:#32770; INSTANCE:1]"
    Local Const $sTRAYICONS_LISTVIEW = "[CLASS:SysListView32; INSTANCE:1]"
    Local Const $sLISTVIEW_COMBOX_CONTROL = "[CLASS:ComboBox; INSTANCE:1]"
    Local Const $sTASKBAR_CHILD_OK_BUTTON = "[CLASS:Button; INSTANCE:2]"
    Local Const $iRUNDLL32 = Run($sOPTIONS_DIALOG_PROCESS)
    WinWait($sTASKBAR_PROPERTIES_TITLE, "", 2000)
    Local Const $hTASKBAR_DIALOG = WinGetHandle($sTASKBAR_PROPERTIES_TITLE)
    WinSetState($hTASKBAR_DIALOG, "", $iDebug)
    ControlSend($hTASKBAR_DIALOG, "", ControlGetHandle($hTASKBAR_DIALOG, "", $sCUSTOMIZE_BUTTON), $sSENDKEYS)
    WinWait($sTASKBAR_CUSTOMIZE_TITLE, "", 2000)
    $hTASKBAR_CHILD_DIALOG = WinGetHandle($sTASKBAR_CUSTOMIZE_TITLE)
    WinSetState($hTASKBAR_CHILD_DIALOG, "", $iDebug)
    Local Const $hDIALOG_LISTVIEW = ControlGetHandle($hTASKBAR_CHILD_DIALOG, "", $sTRAYICONS_LISTVIEW)
    Local $iListViewItem = 0, $hComboBox_Instance = 0, $aTrayIcon[1], $iTrayIcon, $iSkipTask = False, $sTrayItemText
    If IsArray($vTrayItems) Or $vTrayItems <> "" Then
        If Not IsArray($vTrayItems) Then
            $aTrayIcon[0] = $vTrayItems
        Else
            $aTrayIcon = $vTrayItems
        EndIf
        For $i = 0 To UBound($aTrayIcon, 1) - 1 Step 1
            $iTrayIcon = _GUICtrlListView_FindInText($hDIALOG_LISTVIEW, $aTrayIcon[$i], $iStartSearchIndex)
            If $iDebug Then
                ConsoleWrite("Tray Icon: " & @TAB & _GUICtrlListView_GetItemText($hDIALOG_LISTVIEW, $iTrayIcon) & @CRLF)
            EndIf
            _GUICtrlListView_SetItemFocused($hDIALOG_LISTVIEW, $iTrayIcon)
            $hComboBox_Instance = ControlGetHandle($hTASKBAR_CHILD_DIALOG, "", $sLISTVIEW_COMBOX_CONTROL)
            ControlSend($hTASKBAR_CHILD_DIALOG, "", $hDIALOG_LISTVIEW, "{SPACE}")
            For $iLoopIndex = 1 To 3 Step 1
                ControlSend($hTASKBAR_CHILD_DIALOG, "", $hComboBox_Instance, "{DOWN}")
            Next
            If $iSystemTrayState <> 5 Then
                ControlSend($hTASKBAR_CHILD_DIALOG, "", $hComboBox_Instance, "{UP}")
                If $iSystemTrayState = 2 Then
                    ControlSend($hTASKBAR_CHILD_DIALOG, "", $hComboBox_Instance, "{UP}")
                EndIf
            EndIf
        Next
        $iSkipTask = True
    EndIf
    While WinExists($hTASKBAR_CHILD_DIALOG)
        If $iSkipTask Then
            ExitLoop
        EndIf
        If $iListViewItem >= _GUICtrlListView_GetItemCount($hDIALOG_LISTVIEW) + 1 Then
            ExitLoop
        EndIf
        $iListViewItem += 1
        ControlFocus($hTASKBAR_CHILD_DIALOG, "", $hDIALOG_LISTVIEW)
        If $iDebug Then
            $sTrayItemText = _GUICtrlListView_GetItemText($hDIALOG_LISTVIEW, $iListViewItem)
            If $sTrayItemText <> "" Then
                ConsoleWrite("Tray Icon: " & @TAB & $sTrayItemText & @CRLF)
            EndIf
        EndIf
        $hComboBox_Instance = ControlGetHandle($hTASKBAR_CHILD_DIALOG, "", $sLISTVIEW_COMBOX_CONTROL)
        For $i = 1 To 3 Step 1
            ControlSend($hTASKBAR_CHILD_DIALOG, "", $hComboBox_Instance, "{DOWN}")
        Next
        If $iSystemTrayState <> 5 Then
            ControlSend($hTASKBAR_CHILD_DIALOG, "", $hComboBox_Instance, "{UP}")
            If $iSystemTrayState = 2 Then
                ControlSend($hTASKBAR_CHILD_DIALOG, "", $hComboBox_Instance, "{UP}")
            EndIf
        EndIf
        ControlSend($hTASKBAR_CHILD_DIALOG, "", $hDIALOG_LISTVIEW, "{DOWN}")
    WEnd
    ControlSend($hTASKBAR_CHILD_DIALOG, "", $sTASKBAR_CHILD_OK_BUTTON, "{ENTER}")
    WinClose($hTASKBAR_DIALOG)
    If ProcessExists($iRUNDLL32) Then
        ProcessClose($iRUNDLL32)
    EndIf
EndFunc   ;==>_ToggleSystemTrayState
Edited by Decipher
Spoiler

censored.jpg

 

Link to post
Share on other sites
  • 2 weeks later...

JohnOne,

Do you mind elaborating as to how your implementing the UDF?

Are you just running the example? What OS version are you using?

The best of my knowledge this function works as advertised when used appropiately. ;)

Anonymous

Spoiler

censored.jpg

 

Link to post
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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By UEZ
      I'm searching for a way to set an icon for a system menu entry in the console window. I can add / remove entries but I didn't find a way to set an icon for the entry I made.
      Example:
      #AutoIt3Wrapper_Change2CUI=y #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <GuiMenu.au3> #include <WindowsConstants.au3> Global $id_Test = 5000 Global $hConsole = HWnd(DllCall("kernel32.dll", "hwnd", "GetConsoleWindow")[0]) If Not $hConsole Then Exit HotKeySet("{ESC}", "_Exit") Global $hSysmenu = _GUICtrlMenu_GetSystemMenu($hConsole) Global $iCount = _GUICtrlMenu_GetItemCount ($hSysmenu) _GUICtrlMenu_InsertMenuItem($hSysmenu, $iCount, "Test", $id_Test) _GDIPlus_Startup() $hBitmap_GDI = _GDIPlus_BitmapCreateFromMemory(_Test(), True) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hBitmap_GDI = ' & $hBitmap_GDI & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $hBmp1 = _WinAPI_CreateSolidBitmap($hConsole, 0xFF0000, 16, 16) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hBmp1 = ' & $hBmp1 & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $hBmp2 = _WinAPI_CreateSolidBitmap($hConsole, 0x00FF00, 16, 16) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hBmp2 = ' & $hBmp2 & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console ;ConsoleWrite(_GUICtrlMenu_SetItemBmp($hSysmenu, $id_Test, $hBitmap_GDI, False) & @CRLF) ConsoleWrite(_GUICtrlMenu_SetItemBitmaps($hSysmenu, $id_Test, $hBmp1, $hBmp2, False) & ", " & @error & @CRLF) ;_GUICtrlMenu_SetItemBmp($hSysmenu, $id_Test, 8, False) ;set the default close icon _GDIPlus_Shutdown() Do Sleep(1000) Until False Func _Exit() ConsoleWrite("Bye..." & @CRLF) _GUICtrlMenu_DeleteMenu ($hSysmenu, $id_Test, False) _WinAPI_DeleteObject($hBitmap_GDI) _WinAPI_DeleteObject($hBmp1) _WinAPI_DeleteObject($hBmp2) Exit EndFunc ;Code below was generated by: 'File to Base64 String' Code Generator v1.20 Build 2020-06-05 Func _Test($bSaveBinary = False, $sSavePath = @ScriptDir) Local $Test $Test &= 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA3XAAAN1wFCKJt4AAADKElEQVQ4yz2RT2gcdRTHP7+Z36y7yzZZdvJv22i0rBpiAwnWCMZrUCGIBxEvpQSEHAQhePLkyUKg6Em9iZCcahH0pFYxkIqiIdHKYmPUUHcDmU2TuJnZzc7s/H7PQ5M8ePAu7/M+X56y1hKGYY+IOEDqOI6TzWY1gFIKEcF1XRzHUWmaJnF8bHBy5pfbnz9fb0hBh2F4bm5ubjWKogudTqdVqVT0/Py853kehUKBQqHA2tqaVKtVfenS2P6HH396PDri9D9+cdC/8dkXNW2t9fb29spRFPmtVqtULBaVMYZ8Pk82m8X3farVKjdv3qCn+FbpnFuXfNpQkkwlX33z3RtaKYXW2mqtcV1XtNZks9kzQCaTIeNp4sSh8rAnzSe0HO5bt1arHR51y79pEcEYo05Aylp7OqOUIk0TRp+aYO5Ki3B3VR3s70pictzZGlC5jHW0UgprLVEU4Xke29vbLCwsoLXGcRRxYjk/2MtLz2X4/tvbaO3y9XoPlUe7CI7VAMYYPM+jXC5jrcUYAwipUeSzHhV/k59+bFK5OMytOxco9ezQTQ2A4ujoqDQ+Ph4sLS2JiNiDgwM5PDyQ3SCQ/5ptubv6rsy9XJIfvnxbNv/8W+7d+9deu/aeTE9PB2EYljSAiKje3l7SNCUIAkDQXp77f3zE4uJ1Xnv9KoWRK+zs1DlfHiCXy2OtBcA5AdDpdHBdl4F+n77BEdz2z3zw/iKvvHqVZ194h0wmz0B/Ca094jjmtE4NEBFarRa7jfvkHgqp/rrKxOQzjF6+wtY/u4g9Jo5TfL+EiGCtxVqLFhGUUhhjsNZgrcvqrU948rFhKlNvEkUdtNvBoFEqPVtUSqGUQiulaDabtNttPC/D5t3fqTU0Y5dfpNFogFhEOLsaxzHtdpsgCNT6+rrSSZIwOztrhoeH' $Test &= 'qdfrRmutJp6e4q+tKsbYs3in7+7r65OhoSE9MzNjkiRBt9ttkiRxjTHkcjl3bGxMPYhjSdP0rLvdLt1uF9d1BcDzPHdyclL0yspKuLGxcT0IgkeKxaINgsADXBFxAefEQB4ImNT3/W4Yhk6z2awtLy9H/wPnrsNEnFPl4QAAAABJRU5ErkJggg==' Local $bString = _WinAPI_Base64Decode($Test) If @error Then Return SetError(1, 0, 0) $bString = Binary($bString) If $bSaveBinary Then Local Const $hFile = FileOpen($sSavePath & "\AutoSave_16x16_04.png", 18) If @error Then Return SetError(2, 0, $bString) FileWrite($hFile, $bString) FileClose($hFile) EndIf Return $bString EndFunc ;==>_Test Func _WinAPI_Base64Decode($sB64String) Local $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "ptr", 0, "dword*", 0, "ptr", 0, "ptr", 0) If @error Or Not $aCrypt[0] Then Return SetError(1, 0, "") Local $bBuffer = DllStructCreate("byte[" & $aCrypt[5] & "]") $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "struct*", $bBuffer, "dword*", $aCrypt[5], "ptr", 0, "ptr", 0) If @error Or Not $aCrypt[0] Then Return SetError(2, 0, "") Return DllStructGetData($bBuffer, 1) EndFunc ;==>_WinAPI_Base64Decode  
      You must compile and run it to see the menu entry in the console window.

       
      Any idea?
    • By Jemboy
      Recently I was working on a script with icons using GuiCtrkCreatIcon.
      I decided to change the sub folder name of the icons to a more meaning name, however made a typo.

      I tested the .exe on my test computer and it worked flawlessly (because both icon folder where on my test computer) 😁
      But after I installed the script on the intended computers , I got chaos!😵
      Zooming into the problem, I discovered, that because the icons could not be found, the ControlID were returned with a value of 0
      and thus played havoc within the GuiGetMsg() switch/case statement.
      I have been able to reproduce this  (see example)
      #include <GUIConstantsEx.au3> ;============================================================================================================ ; PLEASE, do not save this example in the example folder: C:\Program Files (x86)\AutoIt3\Examples\Helpfile ;============================================================================================================ Example() Func Example() GUICreate(" My GUI Icons", 250, 250) $Icon1 = GUICtrlCreateIcon("shell32.dll", 10, 20, 20) $Icon2 = GUICtrlCreateIcon(@ScriptDir & '\Extras\horse.ani', -1, 20, 40, 32, 32) $Icon3 = GUICtrlCreateIcon("shell32.dll", 7, 20, 75, 32, 32) GUISetState(@SW_SHOW) ;$Icon2 = -1 ; ==> When this line is uncommented the script "works", so -1 could be a potential fix. ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $Icon2 Beep (500,500) EndSwitch WEnd GUIDelete() EndFunc ;==>Example If you save the above script outside the Autoit example folder and run it, it will keep beeping because GuiCtrlCreatIcon did not find horse.ani and return $Icon2=0.
      At the moment GUICtrlCreateIcon () only returns the conntrolID on success and 0 on failure.
      I would like to propose a return of -1 on failure, so a existing and working script won't go awry when the icon can not be found.
       
    • By yffulf
      Is there probably a way to click ie popup button and hide or invisible popup button in the same time?
      I try to use WinSetState @SW_hide ,
      the result is ie crashing or no response because button hide and the next click command won't work...
      $oForm=_IEFormGetObjByName($oIE,"form1") $obutton=_IEFormElementGetObjByName($oForm,"btn_OK") $hWnd = _IEPropertyGet($oIE, "hwnd") _IEAction($obutton,"focus") ControlSend($hWnd, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "{Enter}") WinWait("", "確定存檔嗎?") WinSetState("","確定存檔嗎?",@SW_Hide) ControlClick("", "確定存檔嗎?", "[CLASS:Button; TEXT:確定; Instance:1;]")  
    • By MONaH-Rasta
      Opt('TrayAutoPause', 0) $iTray1 = TrayCreateItem('Tray 1') TrayItemSetState(-1, 1) TrayCreateItem('') $iTrayMenu1 = TrayCreateMenu('Tray Menu 1') $iTray2 = TrayCreateItem('Tray 2', $iTrayMenu1, -1, 1) TrayItemSetState(-1, 1) $iTray3 = TrayCreateItem('Tray 3', $iTrayMenu1, -1, 1) $iTray4 = TrayCreateItem('Tray 4', $iTrayMenu1, -1, 1) TrayCreateItem('') $iTrayMenu2= TrayCreateMenu('Tray Menu 2') $iTray5 = TrayCreateItem('Tray 5', $iTrayMenu2, -1, 1) TrayItemSetState(-1, 1) $iTray6 = TrayCreateItem('Tray 6', $iTrayMenu2, -1, 1) $iTray7 = TrayCreateItem('Tray 7', $iTrayMenu2, -1, 1) TrayCreateItem('') $iTray8 = TrayCreateItem('Tray 8') $iTray9 = TrayCreateItem('Tray 9') $iTray10 = TrayCreateItem('Tray 10') TrayItemSetState(-1, 1) While True Sleep(1000*5) WEnd When I click on Tray 3 / Tray 4 / Tray 6 / Tray 7 nothing happens. Only Tray 2 and Tray 5 stay checked.
      I have tried setting 
      Opt("TrayMenuMode", 8) In this case radio menuitems act like normal menuitems only looks different.
      I'm using AutoIt v3.3.14.5.
      Tested on Windows 10 LTSC 2019 (1809) x64 version: 10.0.17763 build 17763.475 and Windows Server 2008 R2.
      Tried run script x64 and x86 same result.
      Is this kind a bug or something?
    • By morion84
      Hi, when I call a MsgBox function I can use a "$MB_SERVICE_NOTIFICATION" flag so it will be displayed "on the current active desktop, even if there is no user logged on to the computer.". That works just great. Is there a way to do the same to Autoit GUI Form so it will be visible on desktop even if running from system account and user is not logged?
×
×
  • Create New...