PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/docs/scripts/MinimizeToTrayMenu.ahk

http://github.com/Lexikos/AutoHotkey_L-Docs
AutoHotKey | 249 lines | 140 code | 32 blank | 77 comment | 15 complexity | ac3238f4bde75776b61ba29ab761c61b MD5 | raw file
  1. ; Minimize Window to Tray Menu
  2. ; http://www.autohotkey.com
  3. ; This script assigns a hotkey of your choice to hide any window so that
  4. ; it becomes an entry at the bottom of the script's tray menu. Hidden
  5. ; windows can then be unhidden individually or all at once by selecting
  6. ; the corresponding item on the menu. If the script exits for any reason,
  7. ; all the windows that it hid will be unhidden automatically.
  8. ; CHANGES:
  9. ; July 22, 2005 (changes provided by egilmour):
  10. ; - Added new hotkey to unhide the last hidden window (Win+U)
  11. ;
  12. ; November 3, 2004 (changes provided by trogdor):
  13. ; - Program manager is prevented from being hidden.
  14. ; - If there is no active window, the minimize-to-tray hotkey will have
  15. ; no effect rather than waiting indefinitely.
  16. ;
  17. ; October 23, 2004:
  18. ; - The taskbar is prevented from being hidden.
  19. ; - Some possible problems with long window titles have been fixed.
  20. ; - Windows without a title can be hidden without causing problems.
  21. ; - If the script is running under AHK v1.0.22 or greater, the
  22. ; maximum length of each menu item is increased from 100 to 260.
  23. ; CONFIGURATION SECTION: Change the below values as desired.
  24. ; This is the maximum number of windows to allow to be hidden (having a
  25. ; limit helps performance):
  26. mwt_MaxWindows = 50
  27. ; This is the hotkey used to hide the active window:
  28. mwt_Hotkey = #h ; Win+H
  29. ; This is the hotkey used to unhide the last hidden window:
  30. mwt_UnHotkey = #u ; Win+U
  31. ; If you prefer to have the tray menu empty of all the standard items,
  32. ; such as Help and Pause, use N. Otherwise, use Y:
  33. mwt_StandardMenu = N
  34. ; These next few performance settings help to keep the action within the
  35. ; #HotkeyModifierTimeout period, and thus avoid the need to release and
  36. ; press down the hotkey's modifier if you want to hide more than one
  37. ; window in a row. These settings are not needed you choose to have the
  38. ; script use the keyboard hook via #InstallKeybdHook or other means:
  39. #HotkeyModifierTimeout 100
  40. SetWinDelay 10
  41. SetKeyDelay 0
  42. #SingleInstance ; Allow only one instance of this script to be running.
  43. ; END OF CONFIGURATION SECTION (do not make changes below this point
  44. ; unless you want to change the basic functionality of the script).
  45. Hotkey, %mwt_Hotkey%, mwt_Minimize
  46. Hotkey, %mwt_UnHotkey%, mwt_UnMinimize
  47. ; If the user terminates the script by any means, unhide all the
  48. ; windows first:
  49. OnExit, mwt_RestoreAllThenExit
  50. if mwt_StandardMenu = Y
  51. Menu, Tray, Add
  52. else
  53. {
  54. Menu, Tray, NoStandard
  55. Menu, Tray, Add, E&xit and Unhide All, mwt_RestoreAllThenExit
  56. }
  57. Menu, Tray, Add, &Unhide All Hidden Windows, mwt_RestoreAll
  58. Menu, Tray, Add ; Another separator line to make the above more special.
  59. if a_AhkVersion = ; Since it's blank, version is older than 1.0.22.
  60. mwt_MaxLength = 100
  61. else
  62. mwt_MaxLength = 260 ; Reduce this to restrict the width of the menu.
  63. return ; End of auto-execute section.
  64. mwt_Minimize:
  65. if mwt_WindowCount >= %mwt_MaxWindows%
  66. {
  67. MsgBox No more than %mwt_MaxWindows% may be hidden simultaneously.
  68. return
  69. }
  70. ; Set the "last found window" to simplify and help performance.
  71. ; Since in certain cases it is possible for there to be no active window,
  72. ; a timeout has been added:
  73. WinWait, A,, 2
  74. if ErrorLevel <> 0 ; It timed out, so do nothing.
  75. return
  76. ; Otherwise, the "last found window" has been set and can now be used:
  77. WinGet, mwt_ActiveID, ID
  78. WinGetTitle, mwt_ActiveTitle
  79. WinGetClass, mwt_ActiveClass
  80. if mwt_ActiveClass in Shell_TrayWnd,Progman
  81. {
  82. MsgBox The desktop and taskbar cannot be hidden.
  83. return
  84. }
  85. ; Because hiding the window won't deactivate it, activate the window
  86. ; beneath this one (if any). I tried other ways, but they wound up
  87. ; activating the task bar. This way sends the active window (which is
  88. ; about to be hidden) to the back of the stack, which seems best:
  89. Send, !{esc}
  90. ; Hide it only now that WinGetTitle/WinGetClass above have been run (since
  91. ; by default, those commands cannot detect hidden windows):
  92. WinHide
  93. ; If the title is blank, use the class instead. This serves two purposes:
  94. ; 1) A more meaningful name is used as the menu name.
  95. ; 2) Allows the menu item to be created (otherwise, blank items wouldn't
  96. ; be handled correctly by the various routines below).
  97. if mwt_ActiveTitle =
  98. mwt_ActiveTitle = ahk_class %mwt_ActiveClass%
  99. ; Ensure the title is short enough to fit. mwt_ActiveTitle also serves to
  100. ; uniquely identify this particular menu item.
  101. StringLeft, mwt_ActiveTitle, mwt_ActiveTitle, %mwt_MaxLength%
  102. ; In addition to the tray menu requiring that each menu item name be
  103. ; unique, it must also be unique so that we can reliably look it up in
  104. ; the array when the window is later unhidden. So make it unique if it
  105. ; isn't already:
  106. Loop, %mwt_MaxWindows%
  107. {
  108. if mwt_WindowTitle%a_index% = %mwt_ActiveTitle%
  109. {
  110. ; Match found, so it's not unique.
  111. ; First remove the 0x from the hex number to conserve menu space:
  112. StringTrimLeft, mwt_ActiveIDShort, mwt_ActiveID, 2
  113. StringLen, mwt_ActiveIDShortLength, mwt_ActiveIDShort
  114. StringLen, mwt_ActiveTitleLength, mwt_ActiveTitle
  115. mwt_ActiveTitleLength += %mwt_ActiveIDShortLength%
  116. mwt_ActiveTitleLength += 1 ; +1 the 1 space between title & ID.
  117. if mwt_ActiveTitleLength > %mwt_MaxLength%
  118. {
  119. ; Since menu item names are limted in length, trim the title
  120. ; down to allow just enough room for the Window's Short ID at
  121. ; the end of its name:
  122. TrimCount = %mwt_ActiveTitleLength%
  123. TrimCount -= %mwt_MaxLength%
  124. StringTrimRight, mwt_ActiveTitle, mwt_ActiveTitle, %TrimCount%
  125. }
  126. ; Build unique title:
  127. mwt_ActiveTitle = %mwt_ActiveTitle% %mwt_ActiveIDShort%
  128. break
  129. }
  130. }
  131. ; First, ensure that this ID doesn't already exist in the list, which can
  132. ; happen if a particular window was externally unhidden (or its app unhid
  133. ; it) and now it's about to be re-hidden:
  134. mwt_AlreadyExists = n
  135. Loop, %mwt_MaxWindows%
  136. {
  137. if mwt_WindowID%a_index% = %mwt_ActiveID%
  138. {
  139. mwt_AlreadyExists = y
  140. break
  141. }
  142. }
  143. ; Add the item to the array and to the menu:
  144. if mwt_AlreadyExists = n
  145. {
  146. Menu, Tray, add, %mwt_ActiveTitle%, RestoreFromTrayMenu
  147. mwt_WindowCount += 1
  148. Loop, %mwt_MaxWindows% ; Search for a free slot.
  149. {
  150. ; It should always find a free slot if things are designed right.
  151. if mwt_WindowID%a_index% = ; An empty slot was found.
  152. {
  153. mwt_WindowID%a_index% = %mwt_ActiveID%
  154. mwt_WindowTitle%a_index% = %mwt_ActiveTitle%
  155. break
  156. }
  157. }
  158. }
  159. return
  160. RestoreFromTrayMenu:
  161. Menu, Tray, delete, %A_ThisMenuItem%
  162. ; Find window based on its unique title stored as the menu item name:
  163. Loop, %mwt_MaxWindows%
  164. {
  165. if mwt_WindowTitle%a_index% = %A_ThisMenuItem% ; Match found.
  166. {
  167. StringTrimRight, IDToRestore, mwt_WindowID%a_index%, 0
  168. WinShow, ahk_id %IDToRestore%
  169. WinActivate ahk_id %IDToRestore% ; Sometimes needed.
  170. mwt_WindowID%a_index% = ; Make it blank to free up a slot.
  171. mwt_WindowTitle%a_index% =
  172. mwt_WindowCount -= 1
  173. break
  174. }
  175. }
  176. return
  177. ;; This will pop the last minimized window off the stack and unhide it.
  178. mwt_UnMinimize:
  179. ;; Make sure there's something to unhide.
  180. if mwt_WindowCount > 0
  181. {
  182. ;; Get the id of the last window minimized and unhide it
  183. StringTrimRight, IDToRestore, mwt_WindowID%mwt_WindowCount%, 0
  184. WinShow, ahk_id %IDToRestore%
  185. WinActivate ahk_id %IDToRestore%
  186. ;; Get the menu name of the last window minimized and remove it
  187. StringTrimRight, MenuToRemove, mwt_WindowTitle%mwt_WindowCount%, 0
  188. Menu, Tray, delete, %MenuToRemove%
  189. ;; clean up our 'arrays' and decrement the window count
  190. mwt_WindowID%mwt_WindowCount% =
  191. mwt_WindowTitle%mwt_WindowCount% =
  192. mwt_WindowCount -= 1
  193. }
  194. return
  195. mwt_RestoreAllThenExit:
  196. Gosub, mwt_RestoreAll
  197. ExitApp ; Do a true exit.
  198. mwt_RestoreAll:
  199. Loop, %mwt_MaxWindows%
  200. {
  201. if mwt_WindowID%a_index% <>
  202. {
  203. StringTrimRight, IDToRestore, mwt_WindowID%a_index%, 0
  204. WinShow, ahk_id %IDToRestore%
  205. WinActivate ahk_id %IDToRestore% ; Sometimes needed.
  206. ; Do it this way vs. DeleteAll so that the sep. line and first
  207. ; item are retained:
  208. StringTrimRight, MenuToRemove, mwt_WindowTitle%a_index%, 0
  209. Menu, Tray, delete, %MenuToRemove%
  210. mwt_WindowID%a_index% = ; Make it blank to free up a slot.
  211. mwt_WindowTitle%a_index% =
  212. mwt_WindowCount -= 1
  213. }
  214. if mwt_WindowCount = 0
  215. break
  216. }
  217. return