Skip to content

Commit 85bf859

Browse files
author
all sky
committed
清理托盘图标
1 parent bde8eef commit 85bf859

File tree

2 files changed

+302
-4
lines changed

2 files changed

+302
-4
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
3939
如果检测到ffmpeg.exe进程已退出,说明截屏已完毕(ShareX截mp4或gif调用该进程),那么KeyCastOW程序也将退出
4040

41+
顺便调用`TrayIcon_Clean()`清理托盘图标
42+
4143
>没琢磨怎么隐藏命令行,有人做的比我更好可以Pull提交分支
4244
4345

ShareX.ahk

Lines changed: 300 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,293 @@
11
#Requires AutoHotkey v2.0
22
Persistent
3+
;链接来源于:https://www.autohotkey.com/boards/viewtopic.php?f=27&t=130098&p=573646#p573646
4+
;原作者:
5+
6+
#Warn All, Off
7+
OnError((*) => -1)
8+
9+
; ported to AHK v2.0-beta by @krasnovpro
10+
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=1229
11+
12+
; ----------------------------------------------------------------------------------------------------------------------
13+
; Name ..........: TrayIcon library
14+
; Description ...: Provide some useful functions to deal with Tray icons.
15+
; AHK Version ...: AHK_L 1.1.22.02 x32/64 Unicode
16+
; Code from .....: Sean (http://www.autohotkey.com/forum/viewtopic.php?t=17314)
17+
; Author ........: Cyruz (http://ciroprincipe.info) (http://ahkscript.org/boards/viewtopic.php?f=6&t=1229)
18+
; Mod from ......: Fanatic Guru - Cyruz
19+
; License .......: WTFPL - http://www.wtfpl.net/txt/copying/
20+
; Version Date ..: 2019.03.12
21+
; Upd.20160120 ..: Fanatic Guru - Went through all the data types in the DLL and NumGet and matched them up to MSDN
22+
; ...............: which fixed idCmd.
23+
; Upd.20160308 ..: Fanatic Guru - Fix for Windows 10 NotifyIconOverflowWindow.
24+
; Upd.20180313 ..: Fanatic Guru - Fix problem with "VirtualFreeEx" pointed out by nnnik.
25+
; Upd.20180313 ..: Fanatic Guru - Additional fix for previous Windows 10 NotifyIconOverflowWindow fix breaking non
26+
; ...............: hidden icons.
27+
; Upd.20190312 ..: Cyruz - Added TrayIcon_Set, code merged and refactored.
28+
; ----------------------------------------------------------------------------------------------------------------------
29+
30+
; ----------------------------------------------------------------------------------------------------------------------
31+
; Function ......: TrayIcon_GetInfo
32+
; Description ...: Get a series of useful information about tray icons.
33+
; Parameters ....: sExeName - The exe for which we are searching the tray icon data. Leave it empty to receive data for
34+
; ...............: all tray icons.
35+
; Return ........: oTrayInfo - An array of objects containing tray icons data. Any entry is structured like this:
36+
; ...............: oTrayInfo[A_Index].idx - 0 based tray icon index.
37+
; ...............: oTrayInfo[A_Index].idcmd - Command identifier associated with the button.
38+
; ...............: oTrayInfo[A_Index].pid - Process ID.
39+
; ...............: oTrayInfo[A_Index].uid - Application defined identifier for the icon.
40+
; ...............: oTrayInfo[A_Index].msgid - Application defined callback message.
41+
; ...............: oTrayInfo[A_Index].hicon - Handle to the tray icon.
42+
; ...............: oTrayInfo[A_Index].hwnd - Window handle.
43+
; ...............: oTrayInfo[A_Index].class - Window class.
44+
; ...............: oTrayInfo[A_Index].process - Process executable.
45+
; ...............: oTrayInfo[A_Index].tray - Tray Type (Shell_TrayWnd or NotifyIconOverflowWindow).
46+
; ...............: oTrayInfo[A_Index].tooltip - Tray icon tooltip.
47+
; Info ..........: TB_BUTTONCOUNT message - http://goo.gl/DVxpsg
48+
; ...............: TB_GETBUTTON message - http://goo.gl/2oiOsl
49+
; ...............: TBBUTTON structure - http://goo.gl/EIE21Z
50+
; ----------------------------------------------------------------------------------------------------------------------
51+
52+
TrayIcon_GetInfo(sExeName := "") {
53+
dhw := A_DetectHiddenWindows
54+
DetectHiddenWindows(1)
55+
56+
oTrayInfo := []
57+
for sTray in ["Shell_TrayWnd", "NotifyIconOverflowWindow"] {
58+
idxTB := TrayIcon_GetTrayBar(sTray)
59+
pidTaskbar := WinGetPID("ahk_class " sTray)
60+
61+
hProc := DllCall("OpenProcess", "UInt",0x38, "Int",0, "UInt",pidTaskbar)
62+
pRB := DllCall("VirtualAllocEx", "Ptr",hProc, "Ptr",0, "UPtr",20, "UInt",0x1000, "UInt",0x04)
63+
64+
btn := Buffer(A_Is64bitOS ? 32 : 20, 0)
65+
nfo := Buffer(A_Is64bitOS ? 32 : 24, 0)
66+
tip := Buffer(128 * 2, 0)
67+
68+
res := SendMessage(TB_BUTTONCOUNT := 0x0418, 0, 0, "ToolbarWindow32" idxTB, "ahk_class " sTray)
69+
Loop res {
70+
SendMessage(TB_GETBUTTON := 0x0417, A_Index - 1, pRB, "ToolbarWindow32" idxTB, "ahk_class " sTray)
71+
72+
DllCall("ReadProcessMemory", "Ptr",hProc, "Ptr",pRB, "Ptr",btn.Ptr, "UPtr",btn.Size, "UPtr",0)
73+
iBitmap := NumGet(btn, 0, "Int")
74+
idCmd := NumGet(btn, 4, "Int")
75+
fsState := NumGet(btn, 8, "UChar")
76+
fsStyle := NumGet(btn, 9, "UChar")
77+
dwData := NumGet(btn, A_Is64bitOS ? 16 : 12, "UPtr")
78+
iString := NumGet(btn, A_Is64bitOS ? 24 : 16, "Ptr")
79+
DllCall("ReadProcessMemory", "Ptr",hProc, "Ptr",dwData, "Ptr",nfo.Ptr, "UPtr",nfo.Size, "UPtr",0)
80+
81+
hWnd := NumGet(nfo, 0, "Ptr")
82+
uId := NumGet(nfo, A_Is64bitOS ? 8 : 4, "UInt")
83+
msgId := NumGet(nfo, A_Is64bitOS ? 12 : 8, "UPtr")
84+
hIcon := NumGet(nfo, A_Is64bitOS ? 24 : 20, "Ptr")
85+
86+
nPid := WinGetPID("ahk_id " hWnd)
87+
sProcess := WinGetProcessName("ahk_id " hWnd)
88+
sClass := WinGetClass("ahk_id " hWnd)
89+
90+
If ( (sExeName = "-" && !sProcess) || (sExeName == "--" && !nPid) || (!sExeName) || (sExeName = sProcess) || (sExeName == nPid))
91+
{
92+
DllCall("ReadProcessMemory" , "Ptr",hProc, "Ptr",iString, "Ptr",tip.Ptr, "UPtr",tip.Size, "UPtr",0)
93+
oTrayInfo.Push(Map( "idx" , A_Index - 1
94+
, "idcmd" , idCmd
95+
, "pid" , nPid
96+
, "uid" , uId
97+
, "msgid" , msgId
98+
, "hicon" , hIcon
99+
, "hwnd" , hWnd
100+
, "class" , sClass
101+
, "process" , sProcess
102+
, "tooltip" , StrGet(tip.Ptr, "UTF-16")
103+
, "tray" , sTray))
104+
}
105+
}
106+
DllCall("VirtualFreeEx", "Ptr",hProc, "Ptr",pRB, "UPtr",0, "UInt",0x8000)
107+
DllCall("CloseHandle", "Ptr",hProc)
108+
}
109+
DetectHiddenWindows(dhw)
110+
return oTrayInfo
111+
}
112+
113+
; ----------------------------------------------------------------------------------------------------------------------
114+
; Function .....: TrayIcon_Hide
115+
; Description ..: Hide or unhide a tray icon.
116+
; Parameters ...: idCmd - Command identifier associated with the button.
117+
; ..............: sTray - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
118+
; ..............: bHide - True for hide, False for unhide.
119+
; Info .........: TB_HIDEBUTTON message - http://goo.gl/oelsAa
120+
; ----------------------------------------------------------------------------------------------------------------------
121+
TrayIcon_Hide(idCmd, sTray := "Shell_TrayWnd", bHide := true) {
122+
dhw := A_DetectHiddenWindows
123+
DetectHiddenWindows(1)
124+
idxTB := TrayIcon_GetTrayBar()
125+
SendMessage(TB_HIDEBUTTON := 0x0404, idCmd, bHide, "ToolbarWindow32" idxTB, "ahk_class " sTray)
126+
SendMessage(0x001A, 0, 0,, "ahk_class " sTray)
127+
DetectHiddenWindows(dhw)
128+
}
129+
130+
; ----------------------------------------------------------------------------------------------------------------------
131+
; Function .....: TrayIcon_Delete
132+
; Description ..: Delete a tray icon.
133+
; Parameters ...: idx - 0 based tray icon index.
134+
; ..............: sTray - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
135+
; Info .........: TB_DELETEBUTTON message - http://goo.gl/L0pY4R
136+
; ----------------------------------------------------------------------------------------------------------------------
137+
TrayIcon_Delete(idx, sTray := "Shell_TrayWnd") {
138+
dhw := A_DetectHiddenWindows
139+
DetectHiddenWindows(1)
140+
idxTB := TrayIcon_GetTrayBar()
141+
SendMessage(TB_DELETEBUTTON := 0x0416, idx, 0, "ToolbarWindow32" idxTB, "ahk_class " sTray)
142+
SendMessage(0x001A, 0, 0,, "ahk_class " sTray)
143+
DetectHiddenWindows(dhw)
144+
}
145+
146+
; ----------------------------------------------------------------------------------------------------------------------
147+
; Function .....: TrayIcon_Remove
148+
; Description ..: Remove a Tray icon. It should be more reliable than TrayIcon_Delete.
149+
; Parameters ...: hWnd - Window handle.
150+
; ..............: uId - Application defined identifier for the icon.
151+
; Info .........: NOTIFYICONDATA structure - https://goo.gl/1Xuw5r
152+
; ..............: Shell_NotifyIcon function - https://goo.gl/tTSSBM
153+
; ----------------------------------------------------------------------------------------------------------------------
154+
TrayIcon_Remove(hWnd, uId) {
155+
NID := Buffer(2 * 384 + A_PtrSize * 5 + 40, 0)
156+
NumPut("UPtr", NID.Size, NID, 0)
157+
NumPut("UPtr", hWnd, NID, A_PtrSize)
158+
NumPut("UPtr", uId, NID, A_PtrSize * 2)
159+
return DllCall("Shell32.dll\Shell_NotifyIcon", "UInt",0x2, "UInt",NID.Ptr)
160+
}
161+
162+
; ----------------------------------------------------------------------------------------------------------------------
163+
; Function .....: TrayIcon_Move
164+
; Description ..: Move a tray icon.
165+
; Parameters ...: idxOld - 0 based index of the tray icon to move.
166+
; ..............: idxNew - 0 based index where to move the tray icon.
167+
; ..............: sTray - Place where to find the icon ("Shell_TrayWnd" or "NotifyIconOverflowWindow").
168+
; Info .........: TB_MOVEBUTTON message - http://goo.gl/1F6wPw
169+
; ----------------------------------------------------------------------------------------------------------------------
170+
TrayIcon_Move(idxOld, idxNew, sTray := "Shell_TrayWnd") {
171+
dhw := A_DetectHiddenWindows
172+
DetectHiddenWindows(1)
173+
idxTB := TrayIcon_GetTrayBar()
174+
SendMessage 0x452, idxOld, idxNew, "ToolbarWindow32" idxTB, "ahk_class " sTray ; TB_MOVEBUTTON := 0x452
175+
DetectHiddenWindows(dhw)
176+
}
177+
178+
; ----------------------------------------------------------------------------------------------------------------------
179+
; Function .....: TrayIcon_Set
180+
; Description ..: Modify icon with the given index for the given window.
181+
; Parameters ...: hWnd - Window handle.
182+
; ..............: uId - Application defined identifier for the icon.
183+
; ..............: hIcon - Handle to the tray icon.
184+
; ..............: hIconSmall - Handle to the small icon, for window menubar. Optional.
185+
; ..............: hIconBig - Handle to the big icon, for taskbar. Optional.
186+
; Return .......: True on success, false on failure.
187+
; Info .........: NOTIFYICONDATA structure - https://goo.gl/1Xuw5r
188+
; ..............: Shell_NotifyIcon function - https://goo.gl/tTSSBM
189+
; ----------------------------------------------------------------------------------------------------------------------
190+
TrayIcon_Set(hWnd, uId, hIcon, hIconSmall := 0, hIconBig := 0) {
191+
dhw := A_DetectHiddenWindows
192+
DetectHiddenWindows(1)
193+
if hIconSmall
194+
SendMessage(WM_SETICON := 0x0080, 0, hIconSmall,, "ahk_id " hWnd)
195+
if hIconBig
196+
SendMessage(WM_SETICON := 0x0080, 1, hIconBig,, "ahk_id " hWnd)
197+
DetectHiddenWindows(dhw)
198+
199+
NID := Buffer(2 * 384 + A_PtrSize * 5 + 40, 0)
200+
NumPut("UPtr", NID.Size, NID, 0)
201+
NumPut("UPtr", hWnd, NID, (A_PtrSize == 4)? 4 : 8)
202+
NumPut("UPtr", uId, NID, (A_PtrSize == 4)? 8 : 16)
203+
NumPut("UPtr", 2, NID, (A_PtrSize == 4)? 12 : 20)
204+
NumPut("UPtr", hIcon, NID, (A_PtrSize == 4)? 20 : 32)
205+
206+
return DllCall("Shell32.dll\Shell_NotifyIcon", "UInt",NIM_MODIFY := 0x1, "Ptr",NID.Ptr)
207+
}
208+
209+
; ----------------------------------------------------------------------------------------------------------------------
210+
; Function .....: TrayIcon_GetTrayBar
211+
; Description ..: Get the tray icon handle.
212+
; Parameters ...: sTray - Traybar to retrieve.
213+
; Return .......: Tray icon handle.
214+
; ----------------------------------------------------------------------------------------------------------------------
215+
TrayIcon_GetTrayBar(sTray := "Shell_TrayWnd") {
216+
idxTB := "", nTB := ""
217+
dhw := A_DetectHiddenWindows
218+
DetectHiddenWindows(1)
219+
for k in WinGetControls("ahk_class " sTray)
220+
if RegExMatch(k, "(?<=ToolbarWindow32)\d+(?!.*ToolbarWindow32)", &nTB)
221+
loop nTB[] {
222+
hWnd := ControlGetHwnd("ToolbarWindow32" A_Index, "ahk_class " sTray)
223+
hParent := DllCall("GetParent", "Ptr",hWnd)
224+
sClass := WinGetClass("ahk_id " hParent)
225+
if not (sClass == "SysPager" or sClass == "NotifyIconOverflowWindow")
226+
continue
227+
idxTB := A_Index
228+
break
229+
}
230+
DetectHiddenWindows(dhw)
231+
return idxTB
232+
}
233+
234+
; ----------------------------------------------------------------------------------------------------------------------
235+
; Function .....: TrayIcon_GetHotItem
236+
; Description ..: Get the index of tray's hot item.
237+
; Return .......: Index of tray's hot item.
238+
; Info .........: TB_GETHOTITEM message - http://goo.gl/g70qO2
239+
; ----------------------------------------------------------------------------------------------------------------------
240+
TrayIcon_GetHotItem() {
241+
idxTB := TrayIcon_GetTrayBar()
242+
return SendMessage(TB_GETHOTITEM := 0x0447, 0, 0, "ToolbarWindow32" idxTB, "ahk_class Shell_TrayWnd") << 32 >> 32
243+
}
244+
245+
; ----------------------------------------------------------------------------------------------------------------------
246+
; Function .....: TrayIcon_Button
247+
; Description ..: Simulate mouse button click on a tray icon.
248+
; Parameters ...: sExeName - Executable Process Name of tray icon (case sensitive).
249+
; ..............: sButton - Mouse button to simulate (L, M, R).
250+
; ..............: bDouble - True to double click, false to single click.
251+
; ..............: nIdx - Index of tray icon to click if more than one match.
252+
; ----------------------------------------------------------------------------------------------------------------------
253+
TrayIcon_Button(sExeName, sButton := "L", bDouble := false, nIdx := 1) {
254+
dhw := A_DetectHiddenWindows
255+
DetectHiddenWindows(1)
256+
sButton := "WM_" sButton "BUTTON"
257+
oIcons := TrayIcon_GetInfo(sExeName)
258+
if bDouble
259+
action("DBLCLK")
260+
else
261+
action("DOWN"), action("UP")
262+
DetectHiddenWindows(dhw)
263+
264+
action(arg) {
265+
static actions := Map( "WM_MOUSEMOVE" ,0x0200, "WM_LBUTTONDOWN",0x0201, "WM_LBUTTONUP",0x0202
266+
, "WM_LBUTTONDBLCLK",0x0203, "WM_RBUTTONDOWN",0x0204, "WM_RBUTTONUP",0x0205
267+
, "WM_RBUTTONDBLCLK",0x0206, "WM_MBUTTONDOWN",0x0207, "WM_MBUTTONUP",0x0208
268+
, "WM_MBUTTONDBLCLK",0x0209)
269+
PostMessage(oIcons[nIdx]["msgid"], oIcons[nIdx]["uid"], actions[sButton arg],, "ahk_id " oIcons[nIdx]["hwnd"])
270+
}
271+
}
272+
; ----------------------------------------------------------------------------------------------------------------------
273+
; Function .....: TrayIcon_Clean 清理托盘图标
274+
; Description ..: Removes stale icons (no matching processid).
275+
; 删除过时的图标(没有匹配处理)。
276+
; Parameters ...: bVerbose - True to display output, false (default for no output).
277+
; bVerbose -显示输出为True, false(默认为无输出)。
278+
; Notes ........: Uses modified TrayIcon_GetInfo that accepts sExeName - for no process, and -- for no processid
279+
; 使用修改后的TrayIcon_GetInfo,接受sExeName -(无进程)和——(无进程)----------------------------------------------------------------------------------------------------------------------
280+
TrayIcon_Clean(bVerbose := false)
281+
{
282+
otray:=TrayIcon_GetInfo("")
283+
for i, oIcon in otray
284+
{
285+
if(otray[A_index]["process"]=="")
286+
{
287+
TrayIcon_Remove( otray[A_index]["hwnd"] , otray[A_index]["uid"])
288+
}
289+
}
290+
}
3291

4292
; ShareX程序路径
5293
ShareXPath:="C:\Program Files\ShareX\ShareX.exe"
@@ -39,6 +327,7 @@ ProcessCloseAll(PIDOrName)
39327
ProcessClose PIDOrName
40328
}
41329

330+
; 获取执行命令的输出
42331
GetCMDOutput(command){
43332
Shell := ComObject("WScript.Shell")
44333
exec := Shell.Exec(A_ComSpec " /C " command)
@@ -142,10 +431,13 @@ RunVisualizationKeys(command)
142431
{
143432
ProcessCloseAll "keycastow.exe"
144433
Global stop_bool:=False
434+
TrayIcon_Clean()
435+
436+
437+
145438
}
146439
return
147440
}
148-
149441
; 触发快捷键shift+alt+PrtSc键
150442
^+PrintScreen::
151443
{
@@ -164,17 +456,21 @@ RunVisualizationKeys(command)
164456
#HotIf stop_bool
165457
^+PrintScreen::
166458
{
167-
RunWait ShareXPath " -ScreenRecorderGIF"
459+
RunWait ShareXPath " -StopScreenRecording"
168460
Global stop_bool:=False
461+
169462
return
170463
}
171464
#HotIf
172465

173466
#HotIf stop_bool
174467
+PrintScreen::
175468
{
176-
RunWait ShareXPath " -ScreenRecorder"
469+
RunWait ShareXPath " -StopScreenRecording"
177470
Global stop_bool:=False
471+
178472
return
179473
}
180-
#HotIf
474+
#HotIf
475+
476+

0 commit comments

Comments
 (0)