11# Requires AutoHotkey v2.0
22Persistent
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程序路径
5293ShareXPath:=" C:\Program Files\ShareX\ShareX.exe"
@@ -39,6 +327,7 @@ ProcessCloseAll(PIDOrName)
39327 ProcessClose PIDOrName
40328}
41329
330+ ; 获取执行命令的输出
42331GetCMDOutput (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