ahk结束某程序后,某程序的托盘图标还在显示 Topic is solved

遇到了问题?请先进行搜索(中文和英文),然后在此提问

Moderators: tmplinshi, arcticir

User-AutoHotkey
Posts: 14
Joined: 19 May 2024, 14:04

ahk结束某程序后,某程序的托盘图标还在显示

Post by User-AutoHotkey » 26 May 2024, 14:08

如题,ahk用

Code: Select all

ProcessCloseAll "keycastow.exe"
结束程序运行,但是这样会让右下角任务托盘中的程序还在运行

如果再一次调用该程序,又结束掉,托盘的同一个托盘图标又多出一个了

如图所示:
image.png
image.png (41.88 KiB) Viewed 1085 times
如果鼠标移到已结束任务的托盘图标位置,托盘图标就消失

AHK有什么办法能刷新托盘图标?


User-AutoHotkey
Posts: 14
Joined: 19 May 2024, 14:04

Re: ahk结束某程序后,某程序的托盘图标还在显示

Post by User-AutoHotkey » 30 May 2024, 18:42

sikongshan wrote:
27 May 2024, 00:37
可以参考这个网页

viewtopic.php?t=1229
感谢,V1脚本能解决,但我尝试用V2脚本,就报错:

Code: Select all

Error: Target window not found.

Specifically: ahk_id 11800786

	075: msgId := NumGet(nfo, A_Is64bitOS ? 12 :  8, "UPtr")
	076: hIcon := NumGet(nfo, A_Is64bitOS ? 24 : 20, "Ptr")
▶	078: nPid := WinGetPID("ahk_id " hWnd)
	079: sProcess := WinGetProcessName("ahk_id " hWnd)
	080: sClass := WinGetClass("ahk_id " hWnd)

Call stack:
C:\Users\Administrator\Personal_scripts\Python\PythonScripts\temp2.ahk2 (78) : [WinGetPID] nPid := WinGetPID("ahk_id " hWnd)
C:\Users\Administrator\Personal_scripts\Python\PythonScripts\temp2.ahk2 (78) : [TrayIcon_GetInfo] nPid := WinGetPID("ahk_id " hWnd)
C:\Users\Administrator\Personal_scripts\Python\PythonScripts\temp2.ahk2 (274) : [TrayIcon_Clean] For i, oIcon in TrayIcon_GetInfo("--")
C:\Users\Administrator\Personal_scripts\Python\PythonScripts\temp2.ahk2 (291) : [] TrayIcon_Clean()
> Auto-execute
V2代码报错,有什么解决方案吗?我看了半天文档搞不懂原因

V1代码,正常运行:

Code: Select all

; ----------------------------------------------------------------------------------------------------------------------
; Name ..........: TrayIcon library
; Description ...: Provide some useful functions to deal with Tray icons.
; AHK Version ...: AHK_L 1.1.22.02 x32/64 Unicode
; Code from .....: Sean (http://www.autohotkey.com/forum/viewtopic.php?t=17314)
; Author ........: Cyruz (http://ciroprincipe.info) (http://ahkscript.org/boards/viewtopic.php?f=6&t=1229)
; Mod from ......: Fanatic Guru - Cyruz
; License .......: WTFPL - http://www.wtfpl.net/txt/copying/
; Version Date ..: 2019.03.12
; Upd.20160120 ..: Fanatic Guru - Went through all the data types in the DLL and NumGet and matched them up to MSDN
; ...............:                which fixed idCmd.
; Upd.20160308 ..: Fanatic Guru - Fix for Windows 10 NotifyIconOverflowWindow.
; Upd.20180313 ..: Fanatic Guru - Fix problem with "VirtualFreeEx" pointed out by nnnik.
; Upd.20180313 ..: Fanatic Guru - Additional fix for previous Windows 10 NotifyIconOverflowWindow fix breaking non
; ...............:                hidden icons.
; Upd.20190312 ..: Cyruz        - Added TrayIcon_Set, code merged and refactored.
; ----------------------------------------------------------------------------------------------------------------------

; ----------------------------------------------------------------------------------------------------------------------
; Function ......: TrayIcon_GetInfo
; Description ...: Get a series of useful information about tray icons.
; Parameters ....: sExeName  - The exe for which we are searching the tray icon data. Leave it empty to receive data for 
; ...............:             all tray icons.
; Return ........: oTrayInfo - An array of objects containing tray icons data. Any entry is structured like this:
; ...............:             oTrayInfo[A_Index].idx     - 0 based tray icon index.
; ...............:             oTrayInfo[A_Index].idcmd   - Command identifier associated with the button.
; ...............:             oTrayInfo[A_Index].pid     - Process ID.
; ...............:             oTrayInfo[A_Index].uid     - Application defined identifier for the icon.
; ...............:             oTrayInfo[A_Index].msgid   - Application defined callback message.
; ...............:             oTrayInfo[A_Index].hicon   - Handle to the tray icon.
; ...............:             oTrayInfo[A_Index].hwnd    - Window handle.
; ...............:             oTrayInfo[A_Index].class   - Window class.
; ...............:             oTrayInfo[A_Index].process - Process executable.
; ...............:             oTrayInfo[A_Index].tray    - Tray Type (Shell_TrayWnd or NotifyIconOverflowWindow).
; ...............:             oTrayInfo[A_Index].tooltip - Tray icon tooltip.
; Info ..........: TB_BUTTONCOUNT message - http://goo.gl/DVxpsg
; ...............: TB_GETBUTTON message   - http://goo.gl/2oiOsl
; ...............: TBBUTTON structure     - http://goo.gl/EIE21Z
; ----------------------------------------------------------------------------------------------------------------------

TrayIcon_GetInfo(sExeName := "")
{
    d := A_DetectHiddenWindows
    DetectHiddenWindows, On

    oTrayInfo := []
    For key,sTray in ["Shell_TrayWnd", "NotifyIconOverflowWindow"]
    {
        idxTB := TrayIcon_GetTrayBar(sTray)
        WinGet, pidTaskbar, PID, ahk_class %sTray%
        
        hProc := DllCall("OpenProcess",    UInt,0x38, Int,0, UInt,pidTaskbar)
        pRB   := DllCall("VirtualAllocEx", Ptr,hProc, Ptr,0, UPtr,20, UInt,0x1000, UInt,0x04)

        szBtn := VarSetCapacity(btn, (A_Is64bitOS ? 32 : 20), 0)
        szNfo := VarSetCapacity(nfo, (A_Is64bitOS ? 32 : 24), 0)
        szTip := VarSetCapacity(tip, 128 * 2, 0)

        ; TB_BUTTONCOUNT = 0x0418
        SendMessage, 0x0418, 0, 0, ToolbarWindow32%idxTB%, ahk_class %sTray%
        Loop, %ErrorLevel%
        {
             ; TB_GETBUTTON 0x0417
            SendMessage, 0x0417, A_Index-1, pRB, ToolbarWindow32%idxTB%, ahk_class %sTray%

            DllCall("ReadProcessMemory", Ptr,hProc, Ptr,pRB, Ptr,&btn, UPtr,szBtn, UPtr,0)

            iBitmap := NumGet(btn, 0, "Int")
            idCmd   := NumGet(btn, 4, "Int")
            fsState := NumGet(btn, 8, "UChar")
            fsStyle := NumGet(btn, 9, "UChar")
            dwData  := NumGet(btn, (A_Is64bitOS ? 16 : 12), "UPtr")
            iString := NumGet(btn, (A_Is64bitOS ? 24 : 16), "Ptr")

            DllCall("ReadProcessMemory", Ptr,hProc, Ptr,dwData, Ptr,&nfo, UPtr,szNfo, UPtr,0)

            hWnd  := NumGet(nfo, 0, "Ptr")
            uId   := NumGet(nfo, (A_Is64bitOS ?  8 :  4), "UInt")
            msgId := NumGet(nfo, (A_Is64bitOS ? 12 :  8), "UPtr")
            hIcon := NumGet(nfo, (A_Is64bitOS ? 24 : 20), "Ptr")

            WinGet, nPid, PID, ahk_id %hWnd%
            WinGet, sProcess, ProcessName, ahk_id %hWnd%
            WinGetClass, sClass, ahk_id %hWnd%

            If ( (sExeName = "-" && !sProcess) || (sExeName == "--" && !nPid) || (!sExeName) || (sExeName = sProcess) || (sExeName == nPid))
            {
                DllCall("ReadProcessMemory", Ptr,hProc, Ptr,iString, Ptr,&tip, UPtr,szTip, UPtr,0)
                oTrayInfo.Push({ "idx"     : A_Index-1
                               , "idcmd"   : idCmd
                               , "pid"     : nPid
                               , "uid"     : uId
                               , "msgid"   : msgId
                               , "hicon"   : hIcon
                               , "hwnd"    : hWnd
                               , "class"   : sClass
                               , "process" : sProcess
                               , "tooltip" : StrGet(&tip, "UTF-16")
                               , "tray"    : sTray })
            }
        }
        DllCall("VirtualFreeEx", Ptr,hProc, Ptr,pRB, UPtr,0, UInt,0x8000)
        DllCall("CloseHandle",   Ptr,hProc)
    }
    DetectHiddenWindows, %d%
    Return oTrayInfo
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Hide
; Description ..: Hide or unhide a tray icon.
; Parameters ...: idCmd - Command identifier associated with the button.
; ..............: sTray - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
; ..............: bHide - True for hide, False for unhide.
; Info .........: TB_HIDEBUTTON message - http://goo.gl/oelsAa
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Hide(idCmd, sTray:="Shell_TrayWnd", bHide:=True)
{
    d := A_DetectHiddenWindows
    DetectHiddenWindows, On
    idxTB := TrayIcon_GetTrayBar()
    SendMessage, 0x0404, idCmd, bHide, ToolbarWindow32%idxTB%, ahk_class %sTray% ; TB_HIDEBUTTON
    SendMessage, 0x001A, 0, 0, , ahk_class %sTray%
    DetectHiddenWindows, %d%
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Delete
; Description ..: Delete a tray icon.
; Parameters ...: idx   - 0 based tray icon index.
; ..............: sTray - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
; Info .........: TB_DELETEBUTTON message - http://goo.gl/L0pY4R
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Delete(idx, sTray:="Shell_TrayWnd")
{
    d := A_DetectHiddenWindows
    DetectHiddenWindows, On
    idxTB := TrayIcon_GetTrayBar()
    SendMessage, 0x0416, idx, 0, ToolbarWindow32%idxTB%, ahk_class %sTrayPlace% ; TB_DELETEBUTTON = 0x0416
    SendMessage, 0x001A, 0, 0, , ahk_class %sTrayPlace%
    DetectHiddenWindows, %d%
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Remove
; Description ..: Remove a Tray icon. It should be more reliable than TrayIcon_Delete.
; Parameters ...: hWnd - Window handle.
; ..............: uId  - Application defined identifier for the icon.
; Info .........: NOTIFYICONDATA structure  - https://goo.gl/1Xuw5r
; ..............: Shell_NotifyIcon function - https://goo.gl/tTSSBM
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Remove(hWnd, uId)
{
        VarSetCapacity(NID, szNID := ((A_IsUnicode ? 2 : 1) * 384 + A_PtrSize*5 + 40),0)
        NumPut( szNID, NID, 0           )
        NumPut( hWnd,  NID, A_PtrSize   )
        NumPut( uId,   NID, A_PtrSize*2 )
        Return DllCall("Shell32.dll\Shell_NotifyIcon", UInt,0x2, UInt,&NID)
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Move
; Description ..: Move a tray icon.
; Parameters ...: idxOld - 0 based index of the tray icon to move.
; ..............: idxNew - 0 based index where to move the tray icon.
; ..............: sTray  - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
; Info .........: TB_MOVEBUTTON message - http://goo.gl/1F6wPw
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Move(idxOld, idxNew, sTray := "Shell_TrayWnd")
{
    d := A_DetectHiddenWindows
    DetectHiddenWindows, On
    idxTB := TrayIcon_GetTrayBar()
    SendMessage, 0x452, idxOld, idxNew, ToolbarWindow32%idxTB%, ahk_class %sTrayPlace% ; TB_MOVEBUTTON = 0x452
    DetectHiddenWindows, %d%
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Set
; Description ..: Modify icon with the given index for the given window.
; Parameters ...: hWnd       - Window handle.
; ..............: uId        - Application defined identifier for the icon.
; ..............: hIcon      - Handle to the tray icon.
; ..............: hIconSmall - Handle to the small icon, for window menubar. Optional.
; ..............: hIconBig   - Handle to the big icon, for taskbar. Optional.
; Return .......: True on success, false on failure.
; Info .........: NOTIFYICONDATA structure  - https://goo.gl/1Xuw5r
; ..............: Shell_NotifyIcon function - https://goo.gl/tTSSBM
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Set(hWnd, uId, hIcon, hIconSmall:=0, hIconBig:=0)
{
    d := A_DetectHiddenWindows
    DetectHiddenWindows, On
    ; WM_SETICON = 0x0080
    If ( hIconSmall ) 
        SendMessage, 0x0080, 0, hIconSmall,, ahk_id %hWnd%
    If ( hIconBig )
        SendMessage, 0x0080, 1, hIconBig,, ahk_id %hWnd%
    DetectHiddenWindows, %d%

    VarSetCapacity(NID, szNID := ((A_IsUnicode ? 2 : 1) * 384 + A_PtrSize*5 + 40),0)
    NumPut( szNID, NID, 0                           )
    NumPut( hWnd,  NID, (A_PtrSize == 4) ? 4   : 8  )
    NumPut( uId,   NID, (A_PtrSize == 4) ? 8   : 16 )
    NumPut( 2,     NID, (A_PtrSize == 4) ? 12  : 20 )
    NumPut( hIcon, NID, (A_PtrSize == 4) ? 20  : 32 )
    
    ; NIM_MODIFY := 0x1
    Return DllCall("Shell32.dll\Shell_NotifyIcon", UInt,0x1, Ptr,&NID)
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_GetTrayBar
; Description ..: Get the tray icon handle.
; Parameters ...: sTray - Traybar to retrieve.
; Return .......: Tray icon handle.
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_GetTrayBar(sTray:="Shell_TrayWnd")
{
    d := A_DetectHiddenWindows
    DetectHiddenWindows, On
    WinGet, ControlList, ControlList, ahk_class %sTray%
    RegExMatch(ControlList, "(?<=ToolbarWindow32)\d+(?!.*ToolbarWindow32)", nTB)
    Loop, %nTB%
    {
        ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class %sTray%
        hParent := DllCall( "GetParent", Ptr, hWnd )
        WinGetClass, sClass, ahk_id %hParent%
        If !(sClass == "SysPager" || sClass == "NotifyIconOverflowWindow" )
            Continue
        idxTB := A_Index
        Break
    }
    DetectHiddenWindows, %d%
    Return idxTB
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_GetHotItem
; Description ..: Get the index of tray's hot item.
; Return .......: Index of tray's hot item.
; Info .........: TB_GETHOTITEM message - http://goo.gl/g70qO2
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_GetHotItem()
{
    idxTB := TrayIcon_GetTrayBar()
    SendMessage, 0x0447, 0, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_GETHOTITEM = 0x0447
    Return ErrorLevel << 32 >> 32
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Button
; Description ..: Simulate mouse button click on a tray icon.
; Parameters ...: sExeName - Executable Process Name of tray icon.
; ..............: sButton  - Mouse button to simulate (L, M, R).
; ..............: bDouble  - True to double click, false to single click.
; ..............: nIdx     - Index of tray icon to click if more than one match.
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Button(sExeName, sButton:="L", bDouble:=False, nIdx:=1)
{
    d := A_DetectHiddenWindows
    DetectHiddenWindows, On
    WM_MOUSEMOVE      = 0x0200
    WM_LBUTTONDOWN    = 0x0201
    WM_LBUTTONUP      = 0x0202
    WM_LBUTTONDBLCLK  = 0x0203
    WM_RBUTTONDOWN    = 0x0204
    WM_RBUTTONUP      = 0x0205
    WM_RBUTTONDBLCLK  = 0x0206
    WM_MBUTTONDOWN    = 0x0207
    WM_MBUTTONUP      = 0x0208
    WM_MBUTTONDBLCLK  = 0x0209
    sButton := "WM_" sButton "BUTTON"
    oIcons  := TrayIcon_GetInfo(sExeName)
    If ( bDouble )
        PostMessage, oIcons[nIdx].msgid, oIcons[nIdx].uid, %sButton%DBLCLK,, % "ahk_id " oIcons[nIdx].hwnd
    Else
    {
        PostMessage, oIcons[nIdx].msgid, oIcons[nIdx].uid, %sButton%DOWN,, % "ahk_id " oIcons[nIdx].hwnd
        PostMessage, oIcons[nIdx].msgid, oIcons[nIdx].uid, %sButton%UP,, % "ahk_id " oIcons[nIdx].hwnd
    }
    DetectHiddenWindows, %d%
    Return
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Clean 清理托盘图标
; Description ..: Removes stale icons (no matching processid).
;                 删除过时的图标(没有匹配处理)。
; Parameters ...: bVerbose - True to display output, false (default for no output).
;                 bVerbose -显示输出为True, false(默认为无输出)。
; Notes ........: Uses modified TrayIcon_GetInfo that accepts sExeName - for no process, and -- for no processid
;                 使用修改后的TrayIcon_GetInfo,接受sExeName -(无进程)和——(无进程)----------------------------------------------------------------------------------------------------------------------
TrayIcon_Clean(bVerbose := false)
{
	for i, oIcon in TrayIcon_GetInfo("--") {
		if (not oIcon.pid) {
			TrayIcon_Remove( oIcon.hwnd, oIcon.uid)
			if (bVerbose) {
				str .= "Idx: " oIcon.idx "`nhWnd: " oIcon.hwnd "`nUid: " oIcon.uid "`nIdCmd: " oIcon.idcmd "`n`n"
			}
		}
	}
	if (bVerbose) {
		if (str) {
			str := "Leftover icons removed`n`n" str
		} else {
			str := "No leftover icons to remove"
		}
		MsgBox str
	}
}
TrayIcon_Clean()

V2代码:

Code: Select all

; ported to AHK v2.0-beta by @krasnovpro
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=1229

; ----------------------------------------------------------------------------------------------------------------------
; Name ..........: TrayIcon library
; Description ...: Provide some useful functions to deal with Tray icons.
; AHK Version ...: AHK_L 1.1.22.02 x32/64 Unicode
; Code from .....: Sean (http://www.autohotkey.com/forum/viewtopic.php?t=17314)
; Author ........: Cyruz (http://ciroprincipe.info) (http://ahkscript.org/boards/viewtopic.php?f=6&t=1229)
; Mod from ......: Fanatic Guru - Cyruz
; License .......: WTFPL - http://www.wtfpl.net/txt/copying/
; Version Date ..: 2019.03.12
; Upd.20160120 ..: Fanatic Guru - Went through all the data types in the DLL and NumGet and matched them up to MSDN
; ...............:                which fixed idCmd.
; Upd.20160308 ..: Fanatic Guru - Fix for Windows 10 NotifyIconOverflowWindow.
; Upd.20180313 ..: Fanatic Guru - Fix problem with "VirtualFreeEx" pointed out by nnnik.
; Upd.20180313 ..: Fanatic Guru - Additional fix for previous Windows 10 NotifyIconOverflowWindow fix breaking non
; ...............:                hidden icons.
; Upd.20190312 ..: Cyruz        - Added TrayIcon_Set, code merged and refactored.
; ----------------------------------------------------------------------------------------------------------------------

; ----------------------------------------------------------------------------------------------------------------------
; Function ......: TrayIcon_GetInfo
; Description ...: Get a series of useful information about tray icons.
; Parameters ....: sExeName  - The exe for which we are searching the tray icon data. Leave it empty to receive data for
; ...............:             all tray icons.
; Return ........: oTrayInfo - An array of objects containing tray icons data. Any entry is structured like this:
; ...............:             oTrayInfo[A_Index].idx     - 0 based tray icon index.
; ...............:             oTrayInfo[A_Index].idcmd   - Command identifier associated with the button.
; ...............:             oTrayInfo[A_Index].pid     - Process ID.
; ...............:             oTrayInfo[A_Index].uid     - Application defined identifier for the icon.
; ...............:             oTrayInfo[A_Index].msgid   - Application defined callback message.
; ...............:             oTrayInfo[A_Index].hicon   - Handle to the tray icon.
; ...............:             oTrayInfo[A_Index].hwnd    - Window handle.
; ...............:             oTrayInfo[A_Index].class   - Window class.
; ...............:             oTrayInfo[A_Index].process - Process executable.
; ...............:             oTrayInfo[A_Index].tray    - Tray Type (Shell_TrayWnd or NotifyIconOverflowWindow).
; ...............:             oTrayInfo[A_Index].tooltip - Tray icon tooltip.
; Info ..........: TB_BUTTONCOUNT message - http://goo.gl/DVxpsg
; ...............: TB_GETBUTTON message   - http://goo.gl/2oiOsl
; ...............: TBBUTTON structure     - http://goo.gl/EIE21Z
; ----------------------------------------------------------------------------------------------------------------------

TrayIcon_GetInfo(sExeName := "") {
    dhw := A_DetectHiddenWindows
    DetectHiddenWindows(1)
  
    oTrayInfo    := []
    for sTray in ["Shell_TrayWnd", "NotifyIconOverflowWindow"] {
      idxTB      := TrayIcon_GetTrayBar(sTray)
      pidTaskbar := WinGetPID("ahk_class " sTray)
  
      hProc      := DllCall("OpenProcess",    "UInt",0x38, "Int",0, "UInt",pidTaskbar)
      pRB        := DllCall("VirtualAllocEx", "Ptr",hProc, "Ptr",0, "UPtr",20, "UInt",0x1000, "UInt",0x04)
  
      btn        := Buffer(A_Is64bitOS ? 32 : 20, 0)
      nfo        := Buffer(A_Is64bitOS ? 32 : 24, 0)
      tip        := Buffer(128 * 2, 0)
  
      res := SendMessage(TB_BUTTONCOUNT := 0x0418, 0, 0, "ToolbarWindow32" idxTB, "ahk_class " sTray)
      Loop res {
        SendMessage(TB_GETBUTTON := 0x0417, A_Index - 1, pRB, "ToolbarWindow32" idxTB, "ahk_class " sTray)
  
        DllCall("ReadProcessMemory", "Ptr",hProc, "Ptr",pRB, "Ptr",btn.Ptr, "UPtr",btn.Size, "UPtr",0)
        iBitmap  := NumGet(btn, 0, "Int")
        idCmd    := NumGet(btn, 4, "Int")
        fsState  := NumGet(btn, 8, "UChar")
        fsStyle  := NumGet(btn, 9, "UChar")
        dwData   := NumGet(btn, A_Is64bitOS ? 16 : 12, "UPtr")
        iString  := NumGet(btn, A_Is64bitOS ? 24 : 16, "Ptr")
        DllCall("ReadProcessMemory", "Ptr",hProc, "Ptr",dwData, "Ptr",nfo.Ptr, "UPtr",nfo.Size, "UPtr",0)
  
        hWnd     := NumGet(nfo, 0, "Ptr")
        uId      := NumGet(nfo, A_Is64bitOS ?  8 :  4, "UInt")
        msgId    := NumGet(nfo, A_Is64bitOS ? 12 :  8, "UPtr")
        hIcon    := NumGet(nfo, A_Is64bitOS ? 24 : 20, "Ptr")
  
        nPid     := WinGetPID("ahk_id " hWnd)
        sProcess := WinGetProcessName("ahk_id " hWnd)
        sClass   := WinGetClass("ahk_id " hWnd)
  
        If ( (sExeName = "-" && !sProcess) || (sExeName == "--" && !nPid) || (!sExeName) || (sExeName = sProcess) || (sExeName == nPid))
        {
          DllCall("ReadProcessMemory"   , "Ptr",hProc, "Ptr",iString, "Ptr",tip.Ptr, "UPtr",tip.Size, "UPtr",0)
          oTrayInfo.Push(Map( "idx"     , A_Index - 1
                            , "idcmd"   , idCmd
                            , "pid"     , nPid
                            , "uid"     , uId
                            , "msgid"   , msgId
                            , "hicon"   , hIcon
                            , "hwnd"    , hWnd
                            , "class"   , sClass
                            , "process" , sProcess
                            , "tooltip" , StrGet(tip.Ptr, "UTF-16")
                            , "tray"    , sTray))
        }
      }
      DllCall("VirtualFreeEx", "Ptr",hProc, "Ptr",pRB, "UPtr",0, "UInt",0x8000)
      DllCall("CloseHandle",   "Ptr",hProc)
    }
    DetectHiddenWindows(dhw)
    return oTrayInfo
  }
  
  ; ----------------------------------------------------------------------------------------------------------------------
  ; Function .....: TrayIcon_Hide
  ; Description ..: Hide or unhide a tray icon.
  ; Parameters ...: idCmd - Command identifier associated with the button.
  ; ..............: sTray - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
  ; ..............: bHide - True for hide, False for unhide.
  ; Info .........: TB_HIDEBUTTON message - http://goo.gl/oelsAa
  ; ----------------------------------------------------------------------------------------------------------------------
  TrayIcon_Hide(idCmd, sTray := "Shell_TrayWnd", bHide := true) {
    dhw := A_DetectHiddenWindows
    DetectHiddenWindows(1)
    idxTB := TrayIcon_GetTrayBar()
    SendMessage(TB_HIDEBUTTON := 0x0404, idCmd, bHide, "ToolbarWindow32" idxTB, "ahk_class " sTray)
    SendMessage(0x001A, 0, 0,, "ahk_class " sTray)
    DetectHiddenWindows(dhw)
  }
  
  ; ----------------------------------------------------------------------------------------------------------------------
  ; Function .....: TrayIcon_Delete
  ; Description ..: Delete a tray icon.
  ; Parameters ...: idx   - 0 based tray icon index.
  ; ..............: sTray - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
  ; Info .........: TB_DELETEBUTTON message - http://goo.gl/L0pY4R
  ; ----------------------------------------------------------------------------------------------------------------------
  TrayIcon_Delete(idx, sTray := "Shell_TrayWnd") {
      dhw := A_DetectHiddenWindows
      DetectHiddenWindows(1)
      idxTB := TrayIcon_GetTrayBar()
      SendMessage(TB_DELETEBUTTON := 0x0416, idx, 0, "ToolbarWindow32" idxTB, "ahk_class " sTray)
      SendMessage(0x001A, 0, 0,, "ahk_class " sTray)
      DetectHiddenWindows(dhw)
  }
  
  ; ----------------------------------------------------------------------------------------------------------------------
  ; Function .....: TrayIcon_Remove
  ; Description ..: Remove a Tray icon. It should be more reliable than TrayIcon_Delete.
  ; Parameters ...: hWnd - Window handle.
  ; ..............: uId  - Application defined identifier for the icon.
  ; Info .........: NOTIFYICONDATA structure  - https://goo.gl/1Xuw5r
  ; ..............: Shell_NotifyIcon function - https://goo.gl/tTSSBM
  ; ----------------------------------------------------------------------------------------------------------------------
  TrayIcon_Remove(hWnd, uId) {
    NID := Buffer(2 * 384 + A_PtrSize * 5 + 40, 0)
    NumPut("UPtr", NID.Size, NID, 0)
    NumPut("UPtr", hWnd,     NID, A_PtrSize)
    NumPut("UPtr", uId,      NID, A_PtrSize * 2)
    return DllCall("Shell32.dll\Shell_NotifyIcon", "UInt",0x2, "UInt",NID.Ptr)
  }
  
  ; ----------------------------------------------------------------------------------------------------------------------
  ; Function .....: TrayIcon_Move
  ; Description ..: Move a tray icon.
  ; Parameters ...: idxOld - 0 based index of the tray icon to move.
  ; ..............: idxNew - 0 based index where to move the tray icon.
  ; ..............: sTray  - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
  ; Info .........: TB_MOVEBUTTON message - http://goo.gl/1F6wPw
  ; ----------------------------------------------------------------------------------------------------------------------
  TrayIcon_Move(idxOld, idxNew, sTray := "Shell_TrayWnd") {
    dhw := A_DetectHiddenWindows
    DetectHiddenWindows(1)
    idxTB := TrayIcon_GetTrayBar()
    SendMessage 0x452, idxOld, idxNew, "ToolbarWindow32" idxTB, "ahk_class " sTray ; TB_MOVEBUTTON := 0x452
    DetectHiddenWindows(dhw)
  }
  
  ; ----------------------------------------------------------------------------------------------------------------------
  ; Function .....: TrayIcon_Set
  ; Description ..: Modify icon with the given index for the given window.
  ; Parameters ...: hWnd       - Window handle.
  ; ..............: uId        - Application defined identifier for the icon.
  ; ..............: hIcon      - Handle to the tray icon.
  ; ..............: hIconSmall - Handle to the small icon, for window menubar. Optional.
  ; ..............: hIconBig   - Handle to the big icon, for taskbar. Optional.
  ; Return .......: True on success, false on failure.
  ; Info .........: NOTIFYICONDATA structure  - https://goo.gl/1Xuw5r
  ; ..............: Shell_NotifyIcon function - https://goo.gl/tTSSBM
  ; ----------------------------------------------------------------------------------------------------------------------
  TrayIcon_Set(hWnd, uId, hIcon, hIconSmall := 0, hIconBig := 0) {
    dhw := A_DetectHiddenWindows
    DetectHiddenWindows(1)
    if hIconSmall
      SendMessage(WM_SETICON := 0x0080, 0, hIconSmall,, "ahk_id " hWnd)
    if hIconBig
      SendMessage(WM_SETICON := 0x0080, 1, hIconBig,, "ahk_id " hWnd)
    DetectHiddenWindows(dhw)
  
    NID := Buffer(2 * 384 + A_PtrSize * 5 + 40, 0)
    NumPut("UPtr", NID.Size, NID, 0)
    NumPut("UPtr", hWnd,     NID, (A_PtrSize == 4)? 4  : 8)
    NumPut("UPtr", uId,      NID, (A_PtrSize == 4)? 8  : 16)
    NumPut("UPtr", 2,        NID, (A_PtrSize == 4)? 12 : 20)
    NumPut("UPtr", hIcon,    NID, (A_PtrSize == 4)? 20 : 32)
  
    return DllCall("Shell32.dll\Shell_NotifyIcon", "UInt",NIM_MODIFY := 0x1, "Ptr",NID.Ptr)
  }
  
  ; ----------------------------------------------------------------------------------------------------------------------
  ; Function .....: TrayIcon_GetTrayBar
  ; Description ..: Get the tray icon handle.
  ; Parameters ...: sTray - Traybar to retrieve.
  ; Return .......: Tray icon handle.
  ; ----------------------------------------------------------------------------------------------------------------------
  TrayIcon_GetTrayBar(sTray := "Shell_TrayWnd") {
    idxTB := "", nTB := ""
    dhw := A_DetectHiddenWindows
    DetectHiddenWindows(1)
    for k in WinGetControls("ahk_class " sTray)
      if RegExMatch(k, "(?<=ToolbarWindow32)\d+(?!.*ToolbarWindow32)", &nTB)
        loop nTB[] {
          hWnd    := ControlGetHwnd("ToolbarWindow32" A_Index, "ahk_class " sTray)
          hParent := DllCall("GetParent", "Ptr",hWnd)
          sClass  := WinGetClass("ahk_id " hParent)
          if not (sClass == "SysPager" or sClass == "NotifyIconOverflowWindow")
            continue
          idxTB := A_Index
          break
        }
    DetectHiddenWindows(dhw)
    return idxTB
  }
  
  ; ----------------------------------------------------------------------------------------------------------------------
  ; Function .....: TrayIcon_GetHotItem
  ; Description ..: Get the index of tray's hot item.
  ; Return .......: Index of tray's hot item.
  ; Info .........: TB_GETHOTITEM message - http://goo.gl/g70qO2
  ; ----------------------------------------------------------------------------------------------------------------------
  TrayIcon_GetHotItem() {
    idxTB := TrayIcon_GetTrayBar()
    return SendMessage(TB_GETHOTITEM := 0x0447, 0, 0, "ToolbarWindow32" idxTB, "ahk_class Shell_TrayWnd") << 32 >> 32
  }
  
  ; ----------------------------------------------------------------------------------------------------------------------
  ; Function .....: TrayIcon_Button
  ; Description ..: Simulate mouse button click on a tray icon.
  ; Parameters ...: sExeName - Executable Process Name of tray icon (case sensitive).
  ; ..............: sButton  - Mouse button to simulate (L, M, R).
  ; ..............: bDouble  - True to double click, false to single click.
  ; ..............: nIdx     - Index of tray icon to click if more than one match.
  ; ----------------------------------------------------------------------------------------------------------------------
  TrayIcon_Button(sExeName, sButton := "L", bDouble := false, nIdx := 1) {
    dhw := A_DetectHiddenWindows
    DetectHiddenWindows(1)
    sButton := "WM_" sButton "BUTTON"
    oIcons  := TrayIcon_GetInfo(sExeName)
    if bDouble
      action("DBLCLK")
    else
      action("DOWN"), action("UP")
    DetectHiddenWindows(dhw)
  
    action(arg) {
      static actions := Map(  "WM_MOUSEMOVE"    ,0x0200, "WM_LBUTTONDOWN",0x0201, "WM_LBUTTONUP",0x0202
                            , "WM_LBUTTONDBLCLK",0x0203, "WM_RBUTTONDOWN",0x0204, "WM_RBUTTONUP",0x0205
                            , "WM_RBUTTONDBLCLK",0x0206, "WM_MBUTTONDOWN",0x0207, "WM_MBUTTONUP",0x0208
                            , "WM_MBUTTONDBLCLK",0x0209)
      PostMessage(oIcons[nIdx]["msgid"], oIcons[nIdx]["uid"], actions[sButton arg],, "ahk_id " oIcons[nIdx]["hwnd"])
    }
  }
  ; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Clean 清理托盘图标
; Description ..: Removes stale icons (no matching processid).
;                 删除过时的图标(没有匹配处理)。
; Parameters ...: bVerbose - True to display output, false (default for no output).
;                 bVerbose -显示输出为True, false(默认为无输出)。
; Notes ........: Uses modified TrayIcon_GetInfo that accepts sExeName - for no process, and -- for no processid
;                 使用修改后的TrayIcon_GetInfo,接受sExeName -(无进程)和——(无进程)----------------------------------------------------------------------------------------------------------------------
TrayIcon_Clean(bVerbose := false)
{
	for i, oIcon in TrayIcon_GetInfo("--") {
		if (not oIcon.pid) {
			TrayIcon_Remove( oIcon.hwnd, oIcon.uid)
			if (bVerbose) {
				str .= "Idx: " oIcon.idx "`nhWnd: " oIcon.hwnd "`nUid: " oIcon.uid "`nIdCmd: " oIcon.idcmd "`n`n"
			}
		}
	}
	if (bVerbose) {
		if (str) {
			str := "Leftover icons removed`n`n" str
		} else {
			str := "No leftover icons to remove"
		}
		MsgBox str
	}
}
TrayIcon_Clean()

sikongshan
Posts: 25
Joined: 06 Jul 2019, 21:57

Re: ahk结束某程序后,某程序的托盘图标还在显示  Topic is solved

Post by sikongshan » 30 May 2024, 23:18

还没开始学习V2,对v2语法不熟悉,翻了下帮助。主要是v2莫名其妙针对窗口语句,加入了存在判断,这很不好玩,有这样的错误,整个脚本不运行了。
临时方案,可以在脚本开头加上两句。但是副作用也很明显,有错不报了。

Code: Select all

#Warn All, Off
OnError((*) => -1)
你发的那个v2翻译,因为还看不懂v2的数组写法,所以按照自己的理解,简单粗暴的修改了一下调用部分,你对照改一下
测试可以运行,有效果

Code: Select all

TrayIcon_Clean(bVerbose := false)
{
otray:=TrayIcon_GetInfo("") 
for i, oIcon in otray
{
  if(otray[A_index]["process"]=="") 
  {
    TrayIcon_Remove( otray[A_index]["hwnd"] , otray[A_index]["uid"])

User-AutoHotkey
Posts: 14
Joined: 19 May 2024, 14:04

Re: ahk结束某程序后,某程序的托盘图标还在显示

Post by User-AutoHotkey » 30 May 2024, 23:55

sikongshan wrote:
30 May 2024, 23:18
还没开始学习V2,对v2语法不熟悉,翻了下帮助。主要是v2莫名其妙针对窗口语句,加入了存在判断,这很不好玩,有这样的错误,整个脚本不运行了。
临时方案,可以在脚本开头加上两句。但是副作用也很明显,有错不报了。

Code: Select all

#Warn All, Off
OnError((*) => -1)
你发的那个v2翻译,因为还看不懂v2的数组写法,所以按照自己的理解,简单粗暴的修改了一下调用部分,你对照改一下
测试可以运行,有效果

Code: Select all

TrayIcon_Clean(bVerbose := false)
{
otray:=TrayIcon_GetInfo("") 
for i, oIcon in otray
{
  if(otray[A_index]["process"]=="") 
  {
    TrayIcon_Remove( otray[A_index]["hwnd"] , otray[A_index]["uid"])
相关帖子已发 viewtopic.php?f=82&t=130372

实际上,用你给的

Code: Select all

#Warn All, Off
OnError((*) => -1)
或者使用Try{}语法,WinExists啥的,但它不会使V2脚本正常工作


我是调用https://github.com/allrobot/KeyCastOW_chinese 某程序结束运行后有残留的图标,V1脚本能正常工作,期望V2脚本能够完美清理残留图标
Image

sikongshan
Posts: 25
Joined: 06 Jul 2019, 21:57

Re: ahk结束某程序后,某程序的托盘图标还在显示

Post by sikongshan » 01 Jun 2024, 02:03

看了你发的帖子,我的意思是:你修改上面我指出的两处以后,是可以完美清除图标的。你在测试一下
我贴一下完整代码

Code: Select all

#Warn All, Off
OnError((*) => -1)
TrayIcon_Clean()
; ported to AHK v2.0-beta by @krasnovpro
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=1229

; ----------------------------------------------------------------------------------------------------------------------
; Name ..........: TrayIcon library
; Description ...: Provide some useful functions to deal with Tray icons.
; AHK Version ...: AHK_L 1.1.22.02 x32/64 Unicode
; Code from .....: Sean (http://www.autohotkey.com/forum/viewtopic.php?t=17314)
; Author ........: Cyruz (http://ciroprincipe.info) (http://ahkscript.org/boards/viewtopic.php?f=6&t=1229)
; Mod from ......: Fanatic Guru - Cyruz
; License .......: WTFPL - http://www.wtfpl.net/txt/copying/
; Version Date ..: 2019.03.12
; Upd.20160120 ..: Fanatic Guru - Went through all the data types in the DLL and NumGet and matched them up to MSDN
; ...............:                which fixed idCmd.
; Upd.20160308 ..: Fanatic Guru - Fix for Windows 10 NotifyIconOverflowWindow.
; Upd.20180313 ..: Fanatic Guru - Fix problem with "VirtualFreeEx" pointed out by nnnik.
; Upd.20180313 ..: Fanatic Guru - Additional fix for previous Windows 10 NotifyIconOverflowWindow fix breaking non
; ...............:                hidden icons.
; Upd.20190312 ..: Cyruz        - Added TrayIcon_Set, code merged and refactored.
; ----------------------------------------------------------------------------------------------------------------------

; ----------------------------------------------------------------------------------------------------------------------
; Function ......: TrayIcon_GetInfo
; Description ...: Get a series of useful information about tray icons.
; Parameters ....: sExeName  - The exe for which we are searching the tray icon data. Leave it empty to receive data for
; ...............:             all tray icons.
; Return ........: oTrayInfo - An array of objects containing tray icons data. Any entry is structured like this:
; ...............:             oTrayInfo[A_Index].idx     - 0 based tray icon index.
; ...............:             oTrayInfo[A_Index].idcmd   - Command identifier associated with the button.
; ...............:             oTrayInfo[A_Index].pid     - Process ID.
; ...............:             oTrayInfo[A_Index].uid     - Application defined identifier for the icon.
; ...............:             oTrayInfo[A_Index].msgid   - Application defined callback message.
; ...............:             oTrayInfo[A_Index].hicon   - Handle to the tray icon.
; ...............:             oTrayInfo[A_Index].hwnd    - Window handle.
; ...............:             oTrayInfo[A_Index].class   - Window class.
; ...............:             oTrayInfo[A_Index].process - Process executable.
; ...............:             oTrayInfo[A_Index].tray    - Tray Type (Shell_TrayWnd or NotifyIconOverflowWindow).
; ...............:             oTrayInfo[A_Index].tooltip - Tray icon tooltip.
; Info ..........: TB_BUTTONCOUNT message - http://goo.gl/DVxpsg
; ...............: TB_GETBUTTON message   - http://goo.gl/2oiOsl
; ...............: TBBUTTON structure     - http://goo.gl/EIE21Z
; ----------------------------------------------------------------------------------------------------------------------

TrayIcon_GetInfo(sExeName := "") {
  dhw := A_DetectHiddenWindows
  DetectHiddenWindows(1)

  oTrayInfo    := []
  for sTray in ["Shell_TrayWnd", "NotifyIconOverflowWindow"] {
    idxTB      := TrayIcon_GetTrayBar(sTray)
    pidTaskbar := WinGetPID("ahk_class " sTray)

    hProc      := DllCall("OpenProcess",    "UInt",0x38, "Int",0, "UInt",pidTaskbar)
    pRB        := DllCall("VirtualAllocEx", "Ptr",hProc, "Ptr",0, "UPtr",20, "UInt",0x1000, "UInt",0x04)

    btn        := Buffer(A_Is64bitOS ? 32 : 20, 0)
    nfo        := Buffer(A_Is64bitOS ? 32 : 24, 0)
    tip        := Buffer(128 * 2, 0)

    res := SendMessage(TB_BUTTONCOUNT := 0x0418, 0, 0, "ToolbarWindow32" idxTB, "ahk_class " sTray)
    Loop res {
      SendMessage(TB_GETBUTTON := 0x0417, A_Index - 1, pRB, "ToolbarWindow32" idxTB, "ahk_class " sTray)

      DllCall("ReadProcessMemory", "Ptr",hProc, "Ptr",pRB, "Ptr",btn.Ptr, "UPtr",btn.Size, "UPtr",0)
      iBitmap  := NumGet(btn, 0, "Int")
      idCmd    := NumGet(btn, 4, "Int")
      fsState  := NumGet(btn, 8, "UChar")
      fsStyle  := NumGet(btn, 9, "UChar")
      dwData   := NumGet(btn, A_Is64bitOS ? 16 : 12, "UPtr")
      iString  := NumGet(btn, A_Is64bitOS ? 24 : 16, "Ptr")
      DllCall("ReadProcessMemory", "Ptr",hProc, "Ptr",dwData, "Ptr",nfo.Ptr, "UPtr",nfo.Size, "UPtr",0)

      hWnd     := NumGet(nfo, 0, "Ptr")
      uId      := NumGet(nfo, A_Is64bitOS ?  8 :  4, "UInt")
      msgId    := NumGet(nfo, A_Is64bitOS ? 12 :  8, "UPtr")
      hIcon    := NumGet(nfo, A_Is64bitOS ? 24 : 20, "Ptr")

      nPid     := WinGetPID("ahk_id " hWnd)
      sProcess := WinGetProcessName("ahk_id " hWnd)
      sClass   := WinGetClass("ahk_id " hWnd)

      If ( (sExeName = "-" && !sProcess) || (sExeName == "--" && !nPid) || (!sExeName) || (sExeName = sProcess) || (sExeName == nPid))
      {
        DllCall("ReadProcessMemory"   , "Ptr",hProc, "Ptr",iString, "Ptr",tip.Ptr, "UPtr",tip.Size, "UPtr",0)
        oTrayInfo.Push(Map( "idx"     , A_Index - 1
                          , "idcmd"   , idCmd
                          , "pid"     , nPid
                          , "uid"     , uId
                          , "msgid"   , msgId
                          , "hicon"   , hIcon
                          , "hwnd"    , hWnd
                          , "class"   , sClass
                          , "process" , sProcess
                          , "tooltip" , StrGet(tip.Ptr, "UTF-16")
                          , "tray"    , sTray))
      }
    }
    DllCall("VirtualFreeEx", "Ptr",hProc, "Ptr",pRB, "UPtr",0, "UInt",0x8000)
    DllCall("CloseHandle",   "Ptr",hProc)
  }
  DetectHiddenWindows(dhw)
  return oTrayInfo
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Hide
; Description ..: Hide or unhide a tray icon.
; Parameters ...: idCmd - Command identifier associated with the button.
; ..............: sTray - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
; ..............: bHide - True for hide, False for unhide.
; Info .........: TB_HIDEBUTTON message - http://goo.gl/oelsAa
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Hide(idCmd, sTray := "Shell_TrayWnd", bHide := true) {
  dhw := A_DetectHiddenWindows
  DetectHiddenWindows(1)
  idxTB := TrayIcon_GetTrayBar()
  SendMessage(TB_HIDEBUTTON := 0x0404, idCmd, bHide, "ToolbarWindow32" idxTB, "ahk_class " sTray)
  SendMessage(0x001A, 0, 0,, "ahk_class " sTray)
  DetectHiddenWindows(dhw)
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Delete
; Description ..: Delete a tray icon.
; Parameters ...: idx   - 0 based tray icon index.
; ..............: sTray - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
; Info .........: TB_DELETEBUTTON message - http://goo.gl/L0pY4R
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Delete(idx, sTray := "Shell_TrayWnd") {
    dhw := A_DetectHiddenWindows
    DetectHiddenWindows(1)
    idxTB := TrayIcon_GetTrayBar()
    SendMessage(TB_DELETEBUTTON := 0x0416, idx, 0, "ToolbarWindow32" idxTB, "ahk_class " sTray)
    SendMessage(0x001A, 0, 0,, "ahk_class " sTray)
    DetectHiddenWindows(dhw)
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Remove
; Description ..: Remove a Tray icon. It should be more reliable than TrayIcon_Delete.
; Parameters ...: hWnd - Window handle.
; ..............: uId  - Application defined identifier for the icon.
; Info .........: NOTIFYICONDATA structure  - https://goo.gl/1Xuw5r
; ..............: Shell_NotifyIcon function - https://goo.gl/tTSSBM
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Remove(hWnd, uId) {
  NID := Buffer(2 * 384 + A_PtrSize * 5 + 40, 0)
  NumPut("UPtr", NID.Size, NID, 0)
  NumPut("UPtr", hWnd,     NID, A_PtrSize)
  NumPut("UPtr", uId,      NID, A_PtrSize * 2)
  return DllCall("Shell32.dll\Shell_NotifyIcon", "UInt",0x2, "UInt",NID.Ptr)
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Move
; Description ..: Move a tray icon.
; Parameters ...: idxOld - 0 based index of the tray icon to move.
; ..............: idxNew - 0 based index where to move the tray icon.
; ..............: sTray  - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
; Info .........: TB_MOVEBUTTON message - http://goo.gl/1F6wPw
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Move(idxOld, idxNew, sTray := "Shell_TrayWnd") {
  dhw := A_DetectHiddenWindows
  DetectHiddenWindows(1)
  idxTB := TrayIcon_GetTrayBar()
  SendMessage 0x452, idxOld, idxNew, "ToolbarWindow32" idxTB, "ahk_class " sTray ; TB_MOVEBUTTON := 0x452
  DetectHiddenWindows(dhw)
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Set
; Description ..: Modify icon with the given index for the given window.
; Parameters ...: hWnd       - Window handle.
; ..............: uId        - Application defined identifier for the icon.
; ..............: hIcon      - Handle to the tray icon.
; ..............: hIconSmall - Handle to the small icon, for window menubar. Optional.
; ..............: hIconBig   - Handle to the big icon, for taskbar. Optional.
; Return .......: True on success, false on failure.
; Info .........: NOTIFYICONDATA structure  - https://goo.gl/1Xuw5r
; ..............: Shell_NotifyIcon function - https://goo.gl/tTSSBM
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Set(hWnd, uId, hIcon, hIconSmall := 0, hIconBig := 0) {
  dhw := A_DetectHiddenWindows
  DetectHiddenWindows(1)
  if hIconSmall
    SendMessage(WM_SETICON := 0x0080, 0, hIconSmall,, "ahk_id " hWnd)
  if hIconBig
    SendMessage(WM_SETICON := 0x0080, 1, hIconBig,, "ahk_id " hWnd)
  DetectHiddenWindows(dhw)

  NID := Buffer(2 * 384 + A_PtrSize * 5 + 40, 0)
  NumPut("UPtr", NID.Size, NID, 0)
  NumPut("UPtr", hWnd,     NID, (A_PtrSize == 4)? 4  : 8)
  NumPut("UPtr", uId,      NID, (A_PtrSize == 4)? 8  : 16)
  NumPut("UPtr", 2,        NID, (A_PtrSize == 4)? 12 : 20)
  NumPut("UPtr", hIcon,    NID, (A_PtrSize == 4)? 20 : 32)

  return DllCall("Shell32.dll\Shell_NotifyIcon", "UInt",NIM_MODIFY := 0x1, "Ptr",NID.Ptr)
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_GetTrayBar
; Description ..: Get the tray icon handle.
; Parameters ...: sTray - Traybar to retrieve.
; Return .......: Tray icon handle.
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_GetTrayBar(sTray := "Shell_TrayWnd") {
  idxTB := "", nTB := ""
  dhw := A_DetectHiddenWindows
  DetectHiddenWindows(1)
  for k in WinGetControls("ahk_class " sTray)
    if RegExMatch(k, "(?<=ToolbarWindow32)\d+(?!.*ToolbarWindow32)", &nTB)
      loop nTB[] {
        hWnd    := ControlGetHwnd("ToolbarWindow32" A_Index, "ahk_class " sTray)
        hParent := DllCall("GetParent", "Ptr",hWnd)
        sClass  := WinGetClass("ahk_id " hParent)
        if not (sClass == "SysPager" or sClass == "NotifyIconOverflowWindow")
          continue
        idxTB := A_Index
        break
      }
  DetectHiddenWindows(dhw)
  return idxTB
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_GetHotItem
; Description ..: Get the index of tray's hot item.
; Return .......: Index of tray's hot item.
; Info .........: TB_GETHOTITEM message - http://goo.gl/g70qO2
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_GetHotItem() {
  idxTB := TrayIcon_GetTrayBar()
  return SendMessage(TB_GETHOTITEM := 0x0447, 0, 0, "ToolbarWindow32" idxTB, "ahk_class Shell_TrayWnd") << 32 >> 32
}

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Button
; Description ..: Simulate mouse button click on a tray icon.
; Parameters ...: sExeName - Executable Process Name of tray icon (case sensitive).
; ..............: sButton  - Mouse button to simulate (L, M, R).
; ..............: bDouble  - True to double click, false to single click.
; ..............: nIdx     - Index of tray icon to click if more than one match.
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Button(sExeName, sButton := "L", bDouble := false, nIdx := 1) {
  dhw := A_DetectHiddenWindows
  DetectHiddenWindows(1)
  sButton := "WM_" sButton "BUTTON"
  oIcons  := TrayIcon_GetInfo(sExeName)
  if bDouble
    action("DBLCLK")
  else
    action("DOWN"), action("UP")
  DetectHiddenWindows(dhw)

  action(arg) {
    static actions := Map(  "WM_MOUSEMOVE"    ,0x0200, "WM_LBUTTONDOWN",0x0201, "WM_LBUTTONUP",0x0202
                          , "WM_LBUTTONDBLCLK",0x0203, "WM_RBUTTONDOWN",0x0204, "WM_RBUTTONUP",0x0205
                          , "WM_RBUTTONDBLCLK",0x0206, "WM_MBUTTONDOWN",0x0207, "WM_MBUTTONUP",0x0208
                          , "WM_MBUTTONDBLCLK",0x0209)
    PostMessage(oIcons[nIdx]["msgid"], oIcons[nIdx]["uid"], actions[sButton arg],, "ahk_id " oIcons[nIdx]["hwnd"])
  }
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Clean 清理托盘图标
; Description ..: Removes stale icons (no matching processid).
;                 删除过时的图标(没有匹配处理)。
; Parameters ...: bVerbose - True to display output, false (default for no output).
;                 bVerbose -显示输出为True, false(默认为无输出)。
; Notes ........: Uses modified TrayIcon_GetInfo that accepts sExeName - for no process, and -- for no processid
;                 使用修改后的TrayIcon_GetInfo,接受sExeName -(无进程)和——(无进程)----------------------------------------------------------------------------------------------------------------------
TrayIcon_Clean(bVerbose := false)
{
otray:=TrayIcon_GetInfo("") 
for i, oIcon in otray
{
  if(otray[A_index]["process"]=="") 
  {
    TrayIcon_Remove( otray[A_index]["hwnd"] , otray[A_index]["uid"])
   if (bVerbose) 
   {
      str .= "Idx: " oIcon.idx "`nhWnd: " oIcon.hwnd "`nUid: " oIcon.uid "`nIdCmd: " oIcon.idcmd "`n`n"
    }
}

if (bVerbose) {
if (str) {
  str := "Leftover icons removed`n`n" str
} else {
  str := "No leftover icons to remove"
}
MsgBox str
}
}
}

User-AutoHotkey
Posts: 14
Joined: 19 May 2024, 14:04

Re: ahk结束某程序后,某程序的托盘图标还在显示

Post by User-AutoHotkey » 01 Jun 2024, 12:51

sikongshan wrote:
01 Jun 2024, 02:03
看了你发的帖子,我的意思是:你修改上面我指出的两处以后,是可以完美清除图标的。你在测试一下
抱歉,我忘了测试后面的

Code: Select all

if(otray[A_index]["process"]=="")


你是对的😂

Post Reply

Return to “请求帮助”