Перейти на главную страничку сайта (список статей, файлы для скачивания)

ФОРУМ (здесь можно обсудить эту статью, а также саму программу AutoHotkey и проблемы её использования)

Проект перевода документации AutoHotkey: перечень переведённых статей и статей в работе.

AutoHotkey: свёртка приложений в трей

Скриптовый язык AutoHotkey предоставляет широкие возможности управления приложениями, в частности, управления окнами (свёртка, скрытие окон и т.д.). Предлагаемый ниже скрипт имитирует свёртку любых приложений в системный трей с последующим доступом к ним чарез контекстное меню иконки скрипта в трее. Данный скрипт является модификацией скрипта "Minimize Window to Tray Menu" из справочного файла AutoHotkey (в статье "AutoHotkey Script Showcase").

Модификация оригинального скрипта преследовала две цели: получить русский интерфейс и обеспечить корректную работу с приложениями, которые открывают скрытые окна или имеют несколько видимых окон. Оригинальный скрипт "плохо" сворачивал в трей такие приложения, как Restorator или ICE Book Reader (они имеют скрытые окна), а также WinAmp или Power DVD (они имеют несколько окон).

Данный скрипт удобно использовать, если вы любите запускать много приложений одновременно, но не хотите, чтобы запущенные приложения "толпились" на панели задач. Кроме того, есть приложения, которые удобно запустить в начале дня и обращаться к ним время от времени (не очень часто) в течение дня. Такие приложения удобно иметь свёрнутыми в трее.

Чтобы установить скрипт, проделайте следующее:

Используйте скрипт следующим образом:

Скрипт рассчитан на то, что язык по умолчанию в системе - русский. Если у вас язык по умолчанию в системе - английский, найдите и замените строки скрипта

mwt_Hotkey = #р ;Win+H
mwt_HotkeyRestoreAll = ^!к ;Ctrl+Alt+R

на такие:

mwt_Hotkey = #h ;Win+H
mwt_HotkeyRestoreAll = ^!r ;Ctrl+Alt+R

Собственно текст скрипта:

;установка иконки скрипта в трее с изображением окошек
Menu, Tray, Icon, %A_WinDir%\system32\Shell32.dll, 99
;максимальное количество окон, которое может быть скрыто
mwt_MaxWindows = 30
;горячая клавиша, скрывающая текущее окно
mwt_Hotkey = #р ;Win+H
;горячая клавиша, восстанавливающая все скрытые окна
mwt_HotkeyRestoreAll = ^!к ;Ctrl+Alt+R
;эта установка убирает "системные" пункты меню иконки скрипта в трее;
;если эти пункты нужны, задайте "Y" вместо "N"
mwt_StandardMenu = N
;следующие настройки позволяют избежать потребности отпускать и
;нажимать снова модификатор горячей клавиши всякий раз,
;когда вы хотите быстро скрыть более, чем одно окно
#HotkeyModifierTimeout 100
SetWinDelay 10
SetKeyDelay 0
;может быть запущено не более одного экземпляра сценария
#SingleInstance
;работать со скрытыми окнами
DetectHiddenWindows, On
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;назначение горячей клавиши, скрывающей текущее окно
Hotkey, %mwt_Hotkey%, mwt_Minimize
;назначение горячей клавиши, восстанавливающей все скрытые окна
Hotkey, %mwt_HotkeyRestoreAll%, mwt_RestoreAll
;при завершении сценария необходимо отобразить все скрытые окна, если таковые есть
OnExit, mwt_RestoreAllThenExit
;настройка меню иконки скрипта в трее
if mwt_StandardMenu = Y
	Menu, Tray, Add
else
{
	Menu, Tray, NoStandard
	Menu, Tray, Add, Выход и восстановление всех скрытых окон, mwt_RestoreAllThenExit
}
Menu, Tray, Add, Восстановление всех скрытых окон, mwt_RestoreAll
Menu, Tray, Add
;ограничение ширины меню
if a_AhkVersion = ;пусто (для версий ранее 1.0.22)
	mwt_MaxLength = 100
else
	mwt_MaxLength = 260
return ;конец секции авто-выполнения скрипта
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;отсюда начинается исполнение, когда нажата горячая клавиша, скрывающая текущее окно
mwt_Minimize:
if mwt_WindowCount >= %mwt_MaxWindows%
{
	MsgBox Не может быть скрыто одновременно больше, чем %mwt_MaxWindows% окон.
	return
}
;получаем активное окно и используем его как "последнее найденное окно",
;т.е. окно по умолчанию для всех дальнейших вызовов функций, связанных с окнами
WinWait, A,, 2
if ErrorLevel <> 0
	return
;получаем информацию об активном окне
WinGet, mwt_ActiveID, ID ;хэндл (HWND) окна
WinGetTitle, mwt_ActiveTitle ;заголовок окна
WinGetClass, mwt_ActiveClass ;имя класса окна
WinGet, mwt_ActivePID, PID ;идентификатор процесса, которому принадлежит окно
WinGet, mwt_List, List, ahk_pid %mwt_ActivePID% ;список всех окон этого процесса
WinGet, mwt_ActiveProcess, ProcessName ;имя процесса, которому принадлежит окно
;рабочий стол и панель задач скрывать нельзя
if mwt_ActiveClass in Shell_TrayWnd,Progman
	return
;поскольку скрытие окна не будет деактивировать его, переключимся
;в другое окно (как будто пользователь нажал Alt+Escape)
Send, !{esc}
;собственно скрываем нужные окна процесса (делаем их невидимыми),
;скрытию подлежат все окна текущего процесса со стилем WS_VISIBLE,
;mwt_WindowsIDs - список хэндлов скрытваемых окон,
;разделённых символом | (вертикальная черта)
mwt_WindowsIDs = ""
;проводник - особый случай, скрывать можно только текущее окно процесса
If mwt_ActiveProcess = explorer.exe
{
	WinHide, ahk_id %mwt_ActiveID%
	mwt_WindowsIDs = %mwt_WindowsIDs%|%mwt_ActiveID%
}
;скрываем все видимые окна процесса
Else
{
	Loop, %mwt_List%
	{
		mwt_id := mwt_List%A_Index%
		WinGet, style, Style, ahk_id %mwt_id%
		if ( style & 0x10000000 ) ;WS_VISIBLE
		{
			WinHide, ahk_id %mwt_id%
			;Result := DllCall("ShowWindow", "UInt", mwt_id, "Int", "0")
			mwt_WindowsIDs = %mwt_WindowsIDs%|%mwt_id%
		}
	}
}
;если заголовок окна пуст, используем имя класса,
;т.к. нам нужен непустой заголовок пункта меню
if mwt_ActiveTitle =
	mwt_ActiveTitle = ahk_class %mwt_ActiveClass%
;обрезаем заголовок окна до максимальной длины mwt_MaxLength
StringLeft, mwt_ActiveTitle, mwt_ActiveTitle, %mwt_MaxLength%
;обеспечение уникальности заголовка пункта меню:
Loop, %mwt_MaxWindows%
{
	if mwt_WindowTitle%a_index% = %mwt_ActiveTitle%
	{
		;Нашли такой же заголовок, так что заголовок не уникален.
		StringTrimLeft, mwt_ActiveIDShort, mwt_ActiveID, 2
		StringLen, mwt_ActiveIDShortLength, mwt_ActiveIDShort
		StringLen, mwt_ActiveTitleLength, mwt_ActiveTitle
		mwt_ActiveTitleLength += %mwt_ActiveIDShortLength%
		mwt_ActiveTitleLength += 1
		if mwt_ActiveTitleLength > %mwt_MaxLength%
		{
			TrimCount = %mwt_ActiveTitleLength%
			TrimCount -= %mwt_MaxLength%
			StringTrimRight, mwt_ActiveTitle, mwt_ActiveTitle, %TrimCount%
		}
		;создаём уникальный заголовок:
		mwt_ActiveTitle = %mwt_ActiveTitle% %mwt_ActiveIDShort%
		break
	}
}
;на всякий случай проверим, нет ли этого окна уже в списке ранее скрытых
mwt_AlreadyExists = n
Loop, %mwt_MaxWindows%
{
	if mwt_WindowID%a_index% = %mwt_ActiveID%
	{
		mwt_AlreadyExists = y
		break
	}
}
;добавим окно в массив и в меню
if mwt_AlreadyExists = n
{
	Menu, Tray, add, %mwt_ActiveTitle%, RestoreFromTrayMenu
	mwt_WindowCount += 1
	Loop, %mwt_MaxWindows% ;поиск свободного элемента в массиве
	{
		if mwt_WindowID%a_index% = ;элемент свободен
		{
			mwt_WindowID%a_index% = %mwt_ActiveID%
			mwt_WindowTitle%a_index% = %mwt_ActiveTitle%
			mwt_WindowPID%a_index% = %mwt_ActivePID%
			mwt_WinIDs%a_index% = %mwt_WindowsIDs%
			break
		}
	}
}
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;отсюда начинается исполнение, когда вызвана команда меню иконки скрипта в трее,
;соответствующая конкретному скрытому окну
RestoreFromTrayMenu:
Menu, Tray, delete, %A_ThisMenuItem%
;поиск окна по его уникальному заголовку, сохраненному как название пункта меню
Loop, %mwt_MaxWindows%
{
	if mwt_WindowTitle%a_index% = %A_ThisMenuItem%
	{
		StringTrimRight, IDToRestore, mwt_WindowID%a_index%, 0
		StringTrimRight, PIDToRestore, mwt_WindowPID%a_index%, 0
		mwt_WindowsIDs := mwt_WinIDs%a_index%
		Loop, parse, mwt_WindowsIDs, |
			WinShow, ahk_id %A_LoopField%
		WinActivate ahk_id %IDToRestore%
		mwt_WindowID%a_index% = ;очищаем элементы массивов
		mwt_WindowTitle%a_index% =
		mwt_WindowPID%a_index% =
		mwt_WinIDs%a_index% =
		mwt_WindowCount -= 1
		break
	}
}
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;отсюда начинается исполнение, когда вызвана команда меню иконки скрипта в трее
;"Выход и восстановление всех скрытых окон"
mwt_RestoreAllThenExit:
Gosub, mwt_RestoreAll
ExitApp ;завершение работы скрипта
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;отсюда начинается исполнение, когда вызвана команда меню иконки скрипта в трее
;"Восстановление всех скрытых окон"
mwt_RestoreAll:
Loop, %mwt_MaxWindows%
{
	if mwt_WindowID%a_index% <>
	{
		StringTrimRight, IDToRestore, mwt_WindowID%a_index%, 0
		StringTrimRight, PIDToRestore, mwt_WindowPID%a_index%, 0
		mwt_WindowsIDs := mwt_WinIDs%a_index%
		Loop, parse, mwt_WindowsIDs, |
			WinShow, ahk_id %A_LoopField%
		WinActivate ahk_id %IDToRestore%
		StringTrimRight, MenuToRemove, mwt_WindowTitle%a_index%, 0
		Menu, Tray, delete, %MenuToRemove%
		mwt_WindowID%a_index% =
		mwt_WindowTitle%a_index% =
		mwt_WindowPID%a_index% =
		mwt_WinIDs%a_index% =
		mwt_WindowCount -= 1
	}
	if mwt_WindowCount = 0
		break
}
return

Скрипт тестировался на Windows XP SP2.

Перейти на главную страничку сайта (список статей, файлы для скачивания)

© 2007 http://www.script-coding.com При любом использовании материалов сайта обязательна ссылка на него как на источник информации, а также сохранение целостности и авторства материалов.