Last active
August 1, 2022 16:53
-
-
Save Otiel/24248595ac4b30366a2228a7ac5ec964 to your computer and use it in GitHub Desktop.
AutoHotkey script to show or hide Slack desktop app
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Include TrayIcon.ahk | |
#s:: | |
; Win S | |
; Show/hide Slack | |
DetectHiddenWindows, Off | |
Process, Exist, slack.exe | |
slackPid = %ErrorLevel% | |
IfWinNotExist, ahk_pid %slackPid% | |
{ | |
TrayIcon_Button("slack.exe") | |
} | |
Else | |
{ | |
IfWinActive, ahk_pid %slackPid% | |
{ | |
WinClose, ahk_pid %slackPid% | |
} | |
Else | |
{ | |
WinActivate, ahk_pid %slackPid% | |
} | |
} | |
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; ---------------------------------------------------------------------------------------------------------------------- | |
; Name ..........: TrayIcon library | |
; Description ...: Provide some useful functions to deal with Tray icons. | |
; AHK Version ...: AHK_L 1.1.22.02 x32/64 Unicode | |
; Original Author: Sean (http://goo.gl/dh0xIX) (http://www.autohotkey.com/forum/viewtopic.php?t=17314) | |
; Update Author .: Cyruz (http://ciroprincipe.info) (http://ahkscript.org/boards/viewtopic.php?f=6&t=1229) | |
; Mod Authors ...: Fanatic Guru, RiseUp | |
; License .......: WTFPL - http://www.wtfpl.net/txt/copying/ | |
; Version Date...: 2017 - 11 - 24 | |
; Note ..........: Many people have updated Sean's original work including me but Cyruz's version seemed the most straight | |
; ...............: forward update for 64 bit so I adapted it with some of the features from my Fanatic Guru version. | |
; Update 20160120: Went through all the data types in the DLL and NumGet and matched them up to MSDN which fixed IDcmd. | |
; Update 20160308: Fix for Windows 10 NotifyIconOverflowWindow | |
; Update 20171124: (RiseUp) Added extra Shell_TrayWnd to account for odd numbering (N) in ToolbarWindow32N | |
; ---------------------------------------------------------------------------------------------------------------------- | |
; ---------------------------------------------------------------------------------------------------------------------- | |
; 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 ........: oTrayIcon_GetInfo - An array of objects containing tray icons data. Any entry is structured like this: | |
; ...............: oTrayIcon_GetInfo[A_Index].idx - 0 based tray icon index. | |
; ...............: oTrayIcon_GetInfo[A_Index].IDcmd - Command identifier associated with the button. | |
; ...............: oTrayIcon_GetInfo[A_Index].pID - Process ID. | |
; ...............: oTrayIcon_GetInfo[A_Index].uID - Application defined identifier for the icon. | |
; ...............: oTrayIcon_GetInfo[A_Index].msgID - Application defined callback message. | |
; ...............: oTrayIcon_GetInfo[A_Index].hIcon - Handle to the tray icon. | |
; ...............: oTrayIcon_GetInfo[A_Index].hWnd - Window handle. | |
; ...............: oTrayIcon_GetInfo[A_Index].Class - Window class. | |
; ...............: oTrayIcon_GetInfo[A_Index].Process - Process executable. | |
; ...............: oTrayIcon_GetInfo[A_Index].Tray - Tray Type (Shell_TrayWnd or NotifyIconOverflowWindow). | |
; ...............: oTrayIcon_GetInfo[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 := "") | |
{ | |
DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" : | |
oTrayIcon_GetInfo := {} | |
For key, sTray in ["NotifyIconOverflowWindow", "Shell_TrayWnd", "Shell_TrayWnd"] | |
{ | |
idxTB := TrayIcon_GetTrayBar() | |
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, 0x4) | |
if (SubStr(A_OSVersion,1,2)=10) | |
SendMessage, 0x418, 0, 0, ToolbarWindow32%key%, ahk_class %sTray% ; TB_BUTTONCOUNT | |
else | |
SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class %sTray% ; TB_BUTTONCOUNT | |
szBtn := VarSetCapacity(btn, (A_Is64bitOS ? 32 : 20), 0) | |
szNfo := VarSetCapacity(nfo, (A_Is64bitOS ? 32 : 24), 0) | |
szTip := VarSetCapacity(tip, 128 * 2, 0) | |
Loop, %ErrorLevel% | |
{ | |
if (SubStr(A_OSVersion,1,2)=10) | |
SendMessage, 0x417, A_Index - 1, pRB, ToolbarWindow32%key%, ahk_class %sTray% ; TB_GETBUTTON | |
else | |
SendMessage, 0x417, A_Index - 1, pRB, ToolbarWindow32%idxTB%, ahk_class %sTray% ; TB_GETBUTTON | |
DllCall("ReadProcessMemory", Ptr, hProc, Ptr, pRB, Ptr, &btn, UPtr, szBtn, UPtr, 0) | |
iBitmap := NumGet(btn, 0, "Int") | |
IDcmd := NumGet(btn, 4, "Int") | |
statyle := NumGet(btn, 8) | |
dwData := NumGet(btn, (A_Is64bitOS ? 16 : 12)) | |
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)) | |
hIcon := NumGet(nfo, (A_Is64bitOS ? 24 : 20), "Ptr") | |
WinGet, pID, PID, ahk_id %hWnd% | |
WinGet, sProcess, ProcessName, ahk_id %hWnd% | |
WinGetClass, sClass, ahk_id %hWnd% | |
If !sExeName || (sExeName = sProcess) || (sExeName = pID) | |
{ | |
DllCall("ReadProcessMemory", Ptr, hProc, Ptr, iString, Ptr, &tip, UPtr, szTip, UPtr, 0) | |
Index := (oTrayIcon_GetInfo.MaxIndex()>0 ? oTrayIcon_GetInfo.MaxIndex()+1 : 1) | |
oTrayIcon_GetInfo[Index,"idx"] := A_Index - 1 | |
oTrayIcon_GetInfo[Index,"IDcmd"] := IDcmd | |
oTrayIcon_GetInfo[Index,"pID"] := pID | |
oTrayIcon_GetInfo[Index,"uID"] := uID | |
oTrayIcon_GetInfo[Index,"msgID"] := msgID | |
oTrayIcon_GetInfo[Index,"hIcon"] := hIcon | |
oTrayIcon_GetInfo[Index,"hWnd"] := hWnd | |
oTrayIcon_GetInfo[Index,"Class"] := sClass | |
oTrayIcon_GetInfo[Index,"Process"] := sProcess | |
oTrayIcon_GetInfo[Index,"Tooltip"] := StrGet(&tip, "UTF-16") | |
oTrayIcon_GetInfo[Index,"Tray"] := sTray | |
} | |
} | |
DllCall("VirtualFreeEx", Ptr, hProc, Ptr, pProc, UPtr, 0, Uint, 0x8000) | |
DllCall("CloseHandle", Ptr, hProc) | |
} | |
DetectHiddenWindows, %Setting_A_DetectHiddenWindows% | |
Return oTrayIcon_GetInfo | |
} | |
; ---------------------------------------------------------------------------------------------------------------------- | |
; Function .....: TrayIcon_Hide | |
; Description ..: Hide or unhide a tray icon. | |
; Parameters ...: IDcmd - Command identifier associated with the button. | |
; ..............: bHide - True for hide, False for unhide. | |
; ..............: sTray - 1 or Shell_TrayWnd || 0 or NotifyIconOverflowWindow. | |
; Info .........: TB_HIDEBUTTON message - http://goo.gl/oelsAa | |
; ---------------------------------------------------------------------------------------------------------------------- | |
TrayIcon_Hide(IDcmd, sTray := "Shell_TrayWnd", bHide:=True) | |
{ | |
(sTray == 0 ? sTray := "NotifyIconOverflowWindow" : sTray == 1 ? sTray := "Shell_TrayWnd" : ) | |
DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" : | |
idxTB := TrayIcon_GetTrayBar() | |
SendMessage, 0x404, IDcmd, bHide, ToolbarWindow32%idxTB%, ahk_class %sTray% ; TB_HIDEBUTTON | |
SendMessage, 0x1A, 0, 0, , ahk_class %sTray% | |
DetectHiddenWindows, %Setting_A_DetectHiddenWindows% | |
} | |
; ---------------------------------------------------------------------------------------------------------------------- | |
; Function .....: TrayIcon_Delete | |
; Description ..: Delete a tray icon. | |
; Parameters ...: idx - 0 based tray icon index. | |
; ..............: sTray - 1 or Shell_TrayWnd || 0 or NotifyIconOverflowWindow. | |
; Info .........: TB_DELETEBUTTON message - http://goo.gl/L0pY4R | |
; ---------------------------------------------------------------------------------------------------------------------- | |
TrayIcon_Delete(idx, sTray := "Shell_TrayWnd") | |
{ | |
(sTray == 0 ? sTray := "NotifyIconOverflowWindow" : sTray == 1 ? sTray := "Shell_TrayWnd" : ) | |
DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" : | |
idxTB := TrayIcon_GetTrayBar() | |
SendMessage, 0x416, idx, 0, ToolbarWindow32%idxTB%, ahk_class %sTray% ; TB_DELETEBUTTON | |
SendMessage, 0x1A, 0, 0, , ahk_class %sTray% | |
DetectHiddenWindows, %Setting_A_DetectHiddenWindows% | |
} | |
; ---------------------------------------------------------------------------------------------------------------------- | |
; Function .....: TrayIcon_Remove | |
; Description ..: Remove a tray icon. | |
; Parameters ...: hWnd, uID. | |
; ---------------------------------------------------------------------------------------------------------------------- | |
TrayIcon_Remove(hWnd, uID) | |
{ | |
NumPut(VarSetCapacity(NID,(A_IsUnicode ? 2 : 1) * 384 + A_PtrSize * 5 + 40,0), NID) | |
NumPut(hWnd , NID, (A_PtrSize == 4 ? 4 : 8 )) | |
NumPut(uID , NID, (A_PtrSize == 4 ? 8 : 16 )) | |
Return DllCall("shell32\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 - 1 or Shell_TrayWnd || 0 or NotifyIconOverflowWindow. | |
; Info .........: TB_MOVEBUTTON message - http://goo.gl/1F6wPw | |
; ---------------------------------------------------------------------------------------------------------------------- | |
TrayIcon_Move(idxOld, idxNew, sTray := "Shell_TrayWnd") | |
{ | |
(sTray == 0 ? sTray := "NotifyIconOverflowWindow" : sTray == 1 ? sTray := "Shell_TrayWnd" : ) | |
DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" : | |
idxTB := TrayIcon_GetTrayBar() | |
SendMessage, 0x452, idxOld, idxNew, ToolbarWindow32%idxTB%, ahk_class %sTray% ; TB_MOVEBUTTON | |
DetectHiddenWindows, %Setting_A_DetectHiddenWindows% | |
} | |
; ---------------------------------------------------------------------------------------------------------------------- | |
; Function .....: TrayIcon_GetTrayBar | |
; Description ..: Get the tray icon handle. | |
; ---------------------------------------------------------------------------------------------------------------------- | |
TrayIcon_GetTrayBar() | |
{ | |
DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_DetectHiddenWindows) ? "On" : | |
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", Ptr, hWnd ) | |
WinGetClass, sClass, ahk_id %hParent% | |
If (sClass <> "SysPager") | |
Continue | |
idxTB := A_Index | |
Break | |
} | |
DetectHiddenWindows, %Setting_A_DetectHiddenWindows% | |
Return idxTB | |
} | |
; ---------------------------------------------------------------------------------------------------------------------- | |
; Function .....: TrayIcon_GetHotItem | |
; Description ..: Get the index of tray's hot item. | |
; Info .........: TB_GETHOTITEM message - http://goo.gl/g70qO2 | |
; ---------------------------------------------------------------------------------------------------------------------- | |
TrayIcon_GetHotItem() | |
{ | |
idxTB := TrayIcon_GetTrayBar() | |
SendMessage, 0x447, 0, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_GETHOTITEM | |
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. | |
; ..............: index - Index of tray icon to click if more than one match. | |
; ---------------------------------------------------------------------------------------------------------------------- | |
TrayIcon_Button(sExeName, sButton := "L", bDouble := false, index := 1) | |
{ | |
DetectHiddenWindows, % (Setting_A_DetectHiddenWindows := A_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 := {} | |
oIcons := TrayIcon_GetInfo(sExeName) | |
msgID := oIcons[index].msgID | |
uID := oIcons[index].uID | |
hWnd := oIcons[index].hWnd | |
if bDouble | |
PostMessage, msgID, uID, %sButton%DBLCLK, , ahk_id %hWnd% | |
else | |
{ | |
PostMessage, msgID, uID, %sButton%DOWN, , ahk_id %hWnd% | |
PostMessage, msgID, uID, %sButton%UP, , ahk_id %hWnd% | |
} | |
DetectHiddenWindows, %Setting_A_DetectHiddenWindows% | |
return | |
} |
Works great, but I didn't like the usage of the needless library - this is just as fast and no dependencies:
; WIN+S - show/hide Slack
#s::
Process, Exist, slack.exe
slackPid = %ErrorLevel%
IfWinNotExist, ahk_pid %slackPid%
{
Run, %A_AppData%\..\Local\slack\slack.exe
}
else
{
IfWinActive, ahk_pid %slackPid%
{
WinClose, ahk_pid %slackPid%
} else {
WinActivate, ahk_pid %slackPid%
}
}
return
Run, %A_AppData%\..\Local\slack\slack.exe
Running the process is slower than clicking on the systray icon.
Hardly, did you take a look at what the 'click the systray icon' script does? It's a HUGE amount of processing, building array of all processes, using process hooks and dll calls...
Anyway, it's instantaneous on my machine.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Works great! Thanks!