Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

RefreshTray()


  • Please log in to reply
7 replies to this topic
HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Remove icons from Tray menu for crashed or terminated scripts\apps.

There was a script that refreshed the tray by moving the mouse over the tray but I cannot find it anymore.
Anyway I have found a solution on web in c++ and did the same in ahk. Sorry if this has been already posted.

So when your script crashes and you call this function try icon will be removed.
It sends mouse movement over the icons trough PostMessage.

RefreshTray(){
	ControlGetPos,,,w,h,ToolbarWindow321, AHK_class Shell_TrayWnd
	width:=w, hight:=h
	While % ((h:=h-5)>0 and w:=width){
		While % ((w:=w-5)>0){
			PostMessage, 0x200,0,% ((hight-h) >> 16)+width-w,ToolbarWindow321, AHK_class Shell_TrayWnd
		}
	}
}


polyethene
  • Members
  • 5519 posts
  • Last active: May 17 2015 06:39 AM
  • Joined: 26 Oct 2012
I never thought this was possible but it actually works! Thanks.

autohotkey.com/net Site Manager

 

Contact me by email (polyethene at autohotkey.net) or message tidbit


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
I've cut down and improved the code ;)

jason_guest
  • Guests
  • Last active:
  • Joined: --
Is there a possibility to refresh the hidden area in Windows 7?
I tried it with following code:
RefreshTray_Win7(){
   DetectHiddenWindows, On
   ControlGetPos,,,w,h,ToolbarWindow321, AHK_class NotifyIconOverflowWindow
   width:=w, hight:=h
   While % ((h:=h-5)>0 and w:=width){
      While % ((w:=w-5)>0){
         PostMessage, 0x200,0,% ((hight-h) >> 16)+width-w,ToolbarWindow321, AHK_class NotifyIconOverflowWindow
      }
   }
}
But this does not work :(

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Sean has written a much better function for that. Extract Information about TrayIcons.
That is what I currently use but it is not 64-bit compatible yet.
TrayIcons() ;will remove dead icons
TrayIcons(sExeName = "")
{
  DetectHiddenWindows,% DHW:=A_DetectHiddenWindows ? "On" : "On"
	WinGet,	pidTaskbar, PID, ahk_class Shell_TrayWnd
	hProc:=	DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
	pProc:=	DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4)
	idxTB:=	GetTrayBar()
  ControlGet,chWnd,HWND,,ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd
	ErrorLevel:=DllCall("SendMessage","UPTR",chWnd,"UInt", 0x418, "UPTR",0,"UPTR", 0,"UPTR")   ; TB_BUTTONCOUNT
	Loop,	%ErrorLevel%
	{
    DllCall("SendMessage","UPTR",chWnd,"UInt",0x417,"UPTR",A_Index-1,"UPTR",pProc) ; TB_GETBUTTON
		VarSetCapacity(btn,32,0), VarSetCapacity(nfo,32,0)
		DllCall("ReadProcessMemory", "UPTR", hProc, "UPTR", pProc, "UPTR", &btn, "Uint", 32, "Uint", 0)
			iBitmap	:= NumGet(btn, 0)
			idn	:= NumGet(btn, 4)
			Statyle := NumGet(btn, 8)
		If	dwData	:= NumGet(btn,12)
			iString	:= NumGet(btn,16)
		Else	dwData	:= NumGet(btn,16,"int64"), iString:=NumGet(btn,24,"int64")
		DllCall("ReadProcessMemory", "UPTR", hProc, "UPTR", dwData, "UPTR", &nfo, "Uint", 32, "Uint", 0)
		If	NumGet(btn,12)
			hWnd	:= NumGet(nfo, 0)
		,	uID	:= NumGet(nfo, 4)
		,	nMsg	:= NumGet(nfo, 8)
		,	hIcon	:= NumGet(nfo,20)
		Else	hWnd	:= NumGet(nfo, 0,"int64"), uID:=NumGet(nfo, 8), nMsg:=NumGet(nfo,12)
    If (!DllCall("IsWindow","UPTR",hwnd))
    {
      IconsToRemove.=hwnd "." uID "."
      Continue
    }
		WinGet, pid, PID,              ahk_id %hWnd%
		WinGet, sProcess, ProcessName, ahk_id %hWnd%
		WinGetClass, sClass,           ahk_id %hWnd%
		If !sExeName || (sExeName = sProcess) || (sExeName = pid)
			VarSetCapacity(sTooltip,128), VarSetCapacity(wTooltip,128*2)
		,	DllCall("ReadProcessMemory", "UPTR", hProc, "UPTR", iString, "UPTR", &wTooltip, "Uint", 128*2, "Uint", 0)
		,	A_IsUnicode ? (sToolTip:=StrGet(&wToolTip)) : DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "str", wTooltip, "int", -1, "str", sTooltip, "int", 128, "Uint", 0, "Uint", 0)
		,	sTrayIcons .= "idx: " . A_Index-1 . " | idn: " . idn . " | Pid: " . pid . " | uID: " . uID . " | MessageID: " . nMsg . " | hWnd: " . hWnd . " | Class: " . sClass . " | Process: " . sProcess . "`n" . "   | Tooltip: " . sTooltip . "`n"
	}
  Loop,Parse,IconsToRemove,.
    If !Mod(A_Index,2)
      RemoveTrayIcon(hwnd,A_LoopField)
    else hwnd:=A_LoopField
  DllCall("VirtualFreeEx", "UPTR", hProc, "UPTR", pProc, "Uint", 0, "Uint", 0x8000)
	DllCall("CloseHandle", "UPTR", hProc)
	DetectHiddenWindows,% DHW
  Return	sTrayIcons
}

RemoveTrayIcon(hWnd, uID, nMsg = 0, hIcon = 0, nRemove = 2)
{
	NumPut(VarSetCapacity(ni,444,0), ni)
	NumPut(hWnd , ni, 4)
	NumPut(uID  , ni, 8)
	NumPut(1|2|4, ni,12)
	NumPut(nMsg , ni,16)
	NumPut(hIcon, ni,20)
	Return	DllCall("shell32\Shell_NotifyIcon" (A_IsUnicode?"W":"A"), "Uint", nRemove, "UPTR", &ni)
}

HideTrayIcon(idn, bHide = True)
{
	idxTB := GetTrayBar()
	SendMessage, 0x404, idn, bHide, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd   ; TB_HIDEBUTTON
	SendMessage, 0x1A, 0, 0, , ahk_class Shell_TrayWnd
}

DeleteTrayIcon(idx)
{
	idxTB := GetTrayBar()
	SendMessage, 0x416, idx - 1, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd   ; TB_DELETEBUTTON
	SendMessage, 0x1A, 0, 0, , ahk_class Shell_TrayWnd
}

MoveTrayIcon(idxOld, idxNew)
{
	idxTB := GetTrayBar()
	SendMessage, 0x452, idxOld - 1, idxNew - 1, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_MOVEBUTTON
}

GetTrayBar()
{
	ControlGet, hParent, hWnd,, TrayNotifyWnd1  , ahk_class Shell_TrayWnd
	ControlGet, hChild , hWnd,, ToolbarWindow321, ahk_id %hParent%
	Loop
	{
		ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class Shell_TrayWnd
		If  Not	hWnd
			Break
		Else If	hWnd = %hChild%
		{
			idxTB := A_Index
			Break
		}
	}
	Return	idxTB
}


jason_guest
  • Guests
  • Last active:
  • Joined: --
Thank you,
I was using these functions before, but mine version has not included the removing of unused icons. Many thanks, it is working great :)

AHK Guest
  • Guests
  • Last active:
  • Joined: --
None of the code here is working for me on XP and HotKeyIt's code returns an error saying Error at line 61. The following variable name contains an illegal character:
"A_IsUnicode?"W"". What's wrong?

AHK Guest
  • Guests
  • Last active:
  • Joined: --
I have sorted it by using AutoHotkey_L.