Jump to content

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

kill process AND tray icon - possible?


  • Please log in to reply
32 replies to this topic
brotherS
  • Members
  • 183 posts
  • Last active: May 05 2017 09:15 AM
  • Joined: 01 Jun 2005
Since he didn't so far, here's my solution :)

GoSub RefreshTray

[...]

#Persistent
RefreshTray:
CoordMode, Mouse, Screen
MouseGetPos, xpos, ypos
MouseMove, 15, 907
MouseMove, 15, 1020
MouseMove, 34, 907
MouseMove, 34, 1020
MouseMove, 52, 907
MouseMove, 52, 1020
MouseMove, 68, 907
MouseMove, 68, 1020
MouseMove, xpos, ypos
return
I tested it and it turned out that AHK's standard mouse speed was just perfect to make this work. My tray is sitting in the left buttom screen corner, so you may have to adjust the values.
DonationCoder.com brings AHK to the newbies!
Fan of AutoHotkey? Consider an occasional donation to its developer, Chris Mallett.

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
Something more effective can perhaps be done using ImageSearch...
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

brotherS
  • Members
  • 183 posts
  • Last active: May 05 2017 09:15 AM
  • Joined: 01 Jun 2005

Something more effective can perhaps be done using ImageSearch...

I tried to use ImageSearch once and failed. Also, my solution above has the benefit that I'm able to use it for all the tasks where I need to refresh the tray area!

:D
DonationCoder.com brings AHK to the newbies!
Fan of AutoHotkey? Consider an occasional donation to its developer, Chris Mallett.

badmojo
  • Members
  • 204 posts
  • Last active: Jul 23 2014 01:39 AM
  • Joined: 11 Nov 2005
tks brotherS, this is something that i was trying to implement for a long time... But your simple solution is brilliant & works well. Btw, i shortened the code somehow by using a loop, maybe it'll be useful to you.

;Source: http://www.autohotkey.com/forum/viewtopic.php?t=8086postorder=asc&start=15
;A quick hack by brotherS to refresh Systray after closing apps.
;Modified to add loop. Systray on the bottom-left

GoSub RefreshTray
Return

#Persistent
RefreshTray:
CoordMode, Mouse, Screen
MouseGetPos, xpos, ypos
xp=730  ; start co-ordinate, to move along horizontally
Loop, 9
{
  MouseMove, %xp%, 750
  xp:=xp+25  ; increment by 25
}
MouseMove, xpos, ypos
Return



brotherS
  • Members
  • 183 posts
  • Last active: May 05 2017 09:15 AM
  • Joined: 01 Jun 2005
Good idea, especially for a tray in the regular place! :)
DonationCoder.com brings AHK to the newbies!
Fan of AutoHotkey? Consider an occasional donation to its developer, Chris Mallett.

padariar
  • Guests
  • Last active:
  • Joined: --

...i shortened the code somehow by using a loop, maybe it'll be useful to you.

(See above)


Thanks a lot. I was able to resolve the similar problem with your code.
Nice help. Thank U once again !!!

Raju C Padaria

jordis
  • Members
  • 81 posts
  • Last active: Aug 22 2014 01:56 PM
  • Joined: 30 Jul 2004
Hi all,
I had the same problem described here: I'm killing a process but the icon will stay in the tray until the mouse hovers over it. I already tried exiting the application with winclose postmessage and the like to no avail, so I had to resort at the mousemove simulation posted above.
However, I improved the code so that the right coordinates are found by getting the position of the taskbar and system tray. The mouse goes through all existing icons.
Also, changing the send method to "Input" makes the execution instantaneous. It really makes a difference. [EDIT]

I tried to comment each step so that anybody can understand what it does. Here it goes:

; IMPORTANT: Tried in Windows 2000 only.
; It works great for me, may need tweak for others.
; It only works with ONE row of icons in the systray.
; (it would need tweaking to pass through multiple rows of icons)
; My systray is located at the standard place: lower right part of screen.

CoordMode, Mouse, Screen
SendMode Input ; You can try "Event" or "Play" for testing the difference
; Get the Y coordinate of the whole task bar, including system tray (Y is enough)
WinGetPos,,Ytaskbar,,,ahk_class Shell_TrayWnd
; Get the specific position of the system tray area, which is a control (X and Width are enough)
ControlGetPos,Xsystray,,Width,,ToolbarWindow321,ahk_class Shell_TrayWnd
; Get current mouse position (to reposition when done)
MouseGetPos, xpos, ypos 
; Calculate Y where mouse will move to [= taskbar's Y + a little bit. 12 works ok for me]
yp:=Ytaskbar+12
; Calculate the maximum X where the mouse can go
maxX:=Xsystray+Width
; Calculate initial X coordinate [= systray's X + a little bit. 5 works ok for me]
xp:=Xsystray+5
; Block user mouse moves (not really necessary, but just in case)
BlockInput,MouseMove
; DEBUG: uncomment the following line for benchmarking
;	StartTime := A_TickCount

; Start loop to move the mouse
Loop
{
  ; if the mouse is moved passed the maximum X, it's done. Exit loop
  if xp>%maxX%
  	break
  ; Move mouse!
  MouseMove, %xp%,%yp%
  ; increment X by 18 (icon width plus 1 or 2 pixels)
  xp:=xp+18
; sendmode Input needs at least sleep,1. If using Sendmode Play/Event you can comment out the following like
  sleep,1
   
}
; Reposition the mouse where it was before staring the script
MouseMove, xpos, ypos
; Unblock user mouse moves
BlockInput,MouseMoveOff

; DEBUG: uncomment the following 2 lines for benchmarking
;	ElapsedTime := A_TickCount - StartTime
;	MsgBox,  %ElapsedTime% milliseconds have elapsed.
Exitapp

regards
jordi

jordis
  • Members
  • 81 posts
  • Last active: Aug 22 2014 01:56 PM
  • Joined: 30 Jul 2004
Hi
This was too good to be true :(
After further testing, I realized that "Sendmode Input" may be too fast. So fast that it does actually not remove the "unwanted" icons from the tray. It needs at least a "sleep,1" for it to work.
I did some testing on what ran faster: Sendmode Input with sleep,1 or Sendmode Play with no sleep
Sendmode Input (with sleep,1) took 375 milliseconds to go through the systray icons.
Sendmode Play (with no sleep) took 390 milliseconds.
Additionally I tested the default Sendmode Event (with no sleep) and it took 600 milliseconds.

So winner is Sendmode Input + sleep,1

Out of curiosity, I tried timing the "Sendmode Input" with no sleep. The result was... 0 seconds! No wonder it didn't remove the icons...

I modified my script above to reflect this.
Also, I'll leave the "timer" code for testing in case anybody would like to try what combination works best for him/her.

Nikolai
  • Guests
  • Last active:
  • Joined: --
It seems to me that I've found solution on MSDN forums, but it is on C++. Can anybody convert in to AutoHotkey?
//Include following code with yours to refresh System Tray.

public const int WM_PAINT = 0xF;
[DllImport("USER32.DLL")]
public static extern int SendMessage(IntPtr hwnd, int msg, int character, IntPtr lpsText);

//Send WM_PAINT Message to paint System Tray which will refresh it.
SendMessage(traynotifywnd,WM_PAINT,0,IntPtr.Zero);
source: http://forums.micros... ... 4&SiteID=1

Mustang
  • Members
  • 421 posts
  • Last active: Dec 26 2010 10:08 PM
  • Joined: 17 May 2007
I believe the ahk conversion would be something like this:
h_Shell_TrayWnd := DllCall("FindWindow", Str, "Shell_TrayWnd", uInt, 0)
h_TrayNotifyWnd := DllCall("FindWindowEx", uInt, h_Shell_TrayWnd, uInt, 0, Str, "TrayNotifyWnd", uInt, 0)
SendMessage, (WM_PAINT:=0xF), 0, 0,, ahk_id %h_TrayNotifyWnd%
However this doesnt refresh the notification area
In either Vista Aero or Vista Classic themes

So Im wondering if the WM_PAINT method works at all
As reported on the link you provided another user (bill_csharper)
Couldnt get it working even in C

engunneer
  • Moderators
  • 9162 posts
  • Last active: Sep 12 2014 10:36 PM
  • Joined: 30 Aug 2005
Mustang,

I am pretty sure
SendMessage, (WM_PAINT:=0xF), 0, 0,, ahk_id %h_TrayNotifyWnd%
;translates to
SendMessage, 1, 0, 0,, ahk_id %h_TrayNotifyWnd%

since the expression is true. (not sure though)
SendMessage, 0xF, 0, 0,, ahk_class Shell_TrayWnd
;and
SendMessage, 0xF, 0, 0,ToolWindow321, ahk_class Shell_TrayWnd

did not work for me either.

DaveAMS
  • Members
  • 4 posts
  • Last active: Feb 28 2008 09:25 PM
  • Joined: 09 Oct 2007
***Disclaimer*** - All of the credit for this code goes to Sean.

I wrote very little code, I only modified his TrayIcon script to find tray icons that no longer had valid processes associated with them, and delete them. This doesn't use a mouse-over, it actually looks at each tray icon and its associated process using the WinAPI (dll calls).

I included both a timer option and the ctl+alt+a hotkey. The hotkey displays a list of the tray icons and their pId's (which in the case of the icons that need to be blown away is null).

About the most substantial change I made from Sean's script was to reverse the loop to count backwards. If it's counting forward and you start deleting things out of the list, the index starts changing and bad things happen. But counting backwards, no problems!

SetTimer, TrayIcons, 500
^!a::msgbox % TrayIcons()

TrayIcons:
TrayIcons()
Return

TrayIcons(sExeName = "")
{
	DetectHiddenWindows, On
	idxTB := GetTrayBar()
	WinGet, pidTaskbar, PID, ahk_class Shell_TrayWnd

	hProc := DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
	pRB := DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 20, "Uint", 0x1000, "Uint", 0x4)

	VarSetCapacity(btn, 20)
	VarSetCapacity(nfo, 24)

	SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd   ; TB_BUTTONCOUNT
	max = %errorlevel%

	Loop, %max%
	{
		i := max - A_index
		SendMessage, 0x417, i, pRB, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd   ; TB_GETBUTTON

		DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pRB, "Uint", &btn, "Uint", 20, "Uint", 0)

		dwData	:= NumGet(btn,12)

		DllCall("ReadProcessMemory", "Uint", hProc, "Uint", dwData, "Uint", &nfo, "Uint", 24, "Uint", 0)

		hWnd	:= NumGet(nfo, 0)

		WinGet, pid, PID,              ahk_id %hWnd%

		ifwinnotexist, ahk_id %hWnd%
		{
		idx := i+1
		;MsgBox, 4, , Delete tray icon %idx%?
		;IfMsgBox Yes
		deletetrayicon(idx)
		}

		tmp = index=%a_index%, i=%i%, pid=%pid%`n
		strayicons .= tmp

	}

	DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pRB, "Uint", 0, "Uint", 0x8000)
	DllCall("CloseHandle", "Uint", hProc)

	Return	sTrayIcons
}

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
}

GetTrayBar()
{
	WinGet, ControlList, ControlList, ahk_class Shell_TrayWnd
	RegExMatch(ControlList, "(?<=ToolbarWindow32)\d+(?!.*ToolbarWindow32)", nTB)

	Loop, %nTB%
	{
		ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class Shell_TrayWnd
		hParent := DllCall("GetParent", "Uint", hWnd)
		WinGetClass, sClass, ahk_id %hParent%
		If (sClass <> "SysPager")
			Continue
		idxTB := A_Index
			Break
	}

	Return	idxTB
}

David <><

smart_john2
  • Members
  • 1 posts
  • Last active: Nov 03 2007 04:04 PM
  • Joined: 03 Nov 2007
Don't use MouseMove() function................it will turn on ur monitor if it is in power saving mode.............just send WM_MOUSEMOVE messages to the "ToolbarWindow321" control with increasing x values. The autoit script code would be like this......the code has been tested and it worked...

Func DeleteTrayIcon()

    AutoItSetOption("WinTitleMatchMode", 4)

    $WindowHandle = WinGetHandle("classname=Shell_TrayWnd")

    $ControlHandle = ControlGetHandle($WindowHandle,"","ToolbarWindow321")

    Local Const $WM_MOUSEMOVE = 0x200
            
    $y = 1

    For $x = 10 To 200 Step 10
                
        $Pos = Int( (2 ^ 16) * $y + $x )

        _SendMessage($ControlHandle, $WM_MOUSEMOVE, 0, $Pos)
        
    Next    

EndFunc 



Christopher Galpin
  • Members
  • 4 posts
  • Last active: Jan 27 2013 04:12 PM
  • Joined: 22 Jul 2007
(Sorry to bump 3 year old post, but figured I'd update it.)
So jordis + smart_john2's code together (thank you both), and in AutoHotkey:

RefreshTray() {
	WM_MOUSEMOVE := 0x200

	ControlGetPos, xTray,, wTray,, ToolbarWindow321, ahk_class Shell_TrayWnd
	endX := xTray + wTray
	x := 5
	y := 12

	Loop
	{
		if (x > endX)
			break
		point := (y << 16) + x
		PostMessage, %WM_MOUSEMOVE%, 0, %point%, ToolbarWindow321, ahk_class Shell_TrayWnd
		x += 18
	}
}

Works fine/great. Could potentially leave > half the lines out and just loop 10, x += 10, and PostMessage, but whatever. Y at 0 works fine for Win7 but maybe not for older OS's.

rhumbus
  • Members
  • 1 posts
  • Last active: Feb 17 2011 03:42 AM
  • Joined: 17 Feb 2011
Swin,
sorry (too) to bring up an aging thread, but it deals with a problem I'm wishing to solve for long time now.
I'm completely clueless of how to put the script together (I gather from your post that it's the combination of 2 scripts from the thread?). I was wondering if you could point to how to put this together in AutoIt, and how can I automate via task scheduler?

Thanks you very much in advance.