Как оставлять окно всегда сверху? Topic is solved

Помощь в написании скриптов
marusa122
Posts: 135
Joined: 22 Mar 2023, 07:48

Как оставлять окно всегда сверху?

10 May 2023, 05:19

Здравствуйте. Есть скрипт, который редактируется с помощью формы. Основная его часть, которая выполняется с настройками, заданными в форме:

Code: Select all

; При нажатии кнопки Start запускаем приложение с указанными в текстовых полях данными
OnButtonRun:
	Gui, Submit
	if (Ed_App4 = "")
	{
	Run %A_ScriptDir%\Шаблон документа.xlsm
	}
	Run %Ed_App4%
	Sleep, 5000
	MsgBox, 64, Программа1, Программа1 запущена! `nЗдесь вы сможете начать работу с выбранным документом, 5
	Return
В данном случае %Ed_App4% - это расположение файла, который должен запускаться (задается в форме для редактирования скрипта). Он не обязательно располагается в %A_ScriptDir% и не обязательно должен иметь расширение .xlsm (это может быть даже .txt, размещенный на флешке). Вопрос: как сделать так, чтобы после запуска и появления-исчезновения MsgBox окно программы с этим файлом (это или Шаблон документа.xlsm, или выбранный в настройках документ) всегда оставалось поверх других окон?
mcl
Posts: 359
Joined: 04 May 2018, 16:35

Re: Как оставлять окно всегда сверху?  Topic is solved

10 May 2023, 06:34

marusa122 wrote: Вопрос: как сделать так, чтобы после запуска и появления-исчезновения MsgBox окно программы с этим файлом всегда оставалось поверх других окон?

Code: Select all

; При нажатии кнопки Start запускаем приложение с указанными в текстовых полях данными
OnButtonRun:
	Gui, Submit
	if (Ed_App4 = "")
	{
		Ed_App4 = %A_ScriptDir%\Шаблон документа.xlsm
	}
	
	; Запоминаем идентификатор процесса запущенной нами программы
	Run %Ed_App4%, %A_ScriptDir%, UseErrorLevel, appPid
	
	If (ErrorLevel == "ERROR") {
		MsgBox 0x30, Какая досада..., Не удалось запустить программу!
		Return
	}
	
	; Ждём, пока появится у запущенной нами программы появится окно
	WinWait ahk_pid %appPid%
	; Если показать сообщение после WinSet AlwaysOnTop, то оно будет под запущенным окном, и мы его не увидим.
	MsgBox, 64, Программа1, Программа1 запущена! `nЗдесь вы сможете начать работу с выбранным документом, 5
	; Ставим окно всегда сверху
	WinSet, AlwaysOnTop, On
	Return
Только помните, что у программы может быть несколько окон, и только первое из них будет всегда сверху.
Например, если в Excel открыть окно VBA-макросов, оно окажется под окном самого Excel.
github://oGDIp - GDI+ wrapper for AHK v1.1
marusa122
Posts: 135
Joined: 22 Mar 2023, 07:48

Re: Как оставлять окно всегда сверху?

10 May 2023, 06:50

mcl, попробовала запустить - окно Экселя оказывается сверху, но если перейти (сделать активным) окно другой программы, это окно Экселя прячется под ним. А оно должно оставаться сверху
mcl
Posts: 359
Joined: 04 May 2018, 16:35

Re: Как оставлять окно всегда сверху?

10 May 2023, 08:05

marusa122 wrote: окно Экселя оказывается сверху, но если перейти (сделать активным) окно другой программы, это окно Экселя прячется под ним. А оно должно оставаться сверху
Действительно. У меня такие результаты:
• Если запускаемый через Run файл создаёт новый процесс, окно оказывается сверху: например, это работает с калькулятором (calc.exe) и картинками (file.jpg). Работает это и с Экселем, если он запускается заново.
• А вот если Эксель уже был открыт, то при открытии .xls-файла новый процесс не запускается, а используется уже имеющийся. И, как следствие, запущенного нами процесса нет, окон у него нет, и скрипт не понимает, какое окно ставить сверху. При этом (по крайней мере, мой) Excel не активирует окно с открытым файлом.

Пока не вижу простого решения, полагая, что пользователь может запускать вашим скриптом что угодно (и поведение запускаемого тоже может быть каким угодно, в зависимости от системы, установленных программ и фазы луны). Разве что можно проверять, запускаем ли мы *.xls*-файл, и если да, активировать Эксель вручную – хоть это и костыль.

Code: Select all

; При нажатии кнопки Start запускаем приложение с указанными в текстовых полях данными
OnButtonRun:
	Gui, Submit
	if (Ed_App4 = "")
	{
		Ed_App4 = %A_ScriptDir%\Шаблон документа.xlsm
	}
	
	Run %Ed_App4%, %A_ScriptDir%, UseErrorLevel
	
	If (ErrorLevel == "ERROR") {
		MsgBox 0x30, Какая досада..., Не удалось запустить программу!
		Return
	}
	
	Sleep 5000
	MsgBox, 64, Программа1, Программа1 запущена! `nЗдесь вы сможете начать работу с выбранным документом, 5
	
	If (Ed_App4 ~= "\.(xls|xlsx|xlsm)$") {
		WinActivate ahk_exe Excel.exe
	}
	
	; Ставим окно всегда сверху
	WinSet, AlwaysOnTop, On, A
	Return
github://oGDIp - GDI+ wrapper for AHK v1.1
marusa122
Posts: 135
Joined: 22 Mar 2023, 07:48

Re: Как оставлять окно всегда сверху?

10 May 2023, 08:24

mcl, попробовала хотя бы с костылем - не помогло. Эксель открывается, но если потом развернуть еще какое-нибудь окно - он скрывается под ним. Возможен ли вариант, чтобы при запуске скрипт как-то "убивал" старый процесс Экселя и запускал новый? Чтобы окно запущенного уже нового процесса оставалось всегда сверху.
mcl
Posts: 359
Joined: 04 May 2018, 16:35

Re: Как оставлять окно всегда сверху?

10 May 2023, 10:41

marusa122 wrote: Эксель открывается, но если потом развернуть еще какое-нибудь окно - он скрывается под ним.
Хм, такого быть не должно. К сожалению, удалённо такие вещи отлаживать тяжело: может, у вас файл зовётся не Excel.exe, а как-то иначе; или Эксель запущен под администратором, и скрипт не имеет над ним власти; или какое-то другое окно (может быть, в том же самом Экселе) оказывается поверх всех, но это неочевидно...

Остаётся только отлаживать скрипт шаг за шагом, проверяя и документируя каждую деталь:

Code: Select all

; При нажатии кнопки Start запускаем приложение с указанными в текстовых полях данными
OnButtonRun:
	Gui, Submit
	if (Ed_App4 = "")
	{
		Ed_App4 = %A_ScriptDir%\Шаблон документа.xlsm
	}
	
	; Отладочная информация будет сохранена в файл my_debug.txt
	debugfile := FileOpen("my_debug.txt", "w")
	
	debugfile.Write("Перед запуском: ")
	GoSub debug_activewindowinfo
	
	WinGet, debug_exstyle, ExStyle, A
	debugfile.WriteLine("Активное окно поверх всех: " (debug_exstyle & 0x8))
	
	debugfile.WriteLine("Пытаемся запустить: " Ed_App4)
	
	Run %Ed_App4%, %A_ScriptDir%, UseErrorLevel, appPid
	
	debugfile.WriteLine("После Run: ErrorLevel = " ErrorLevel)
	debugfile.WriteLine("ID запущенного процесса " appPid)
	
	If (ErrorLevel == "ERROR") {
		MsgBox 0x30, Какая досада..., Не удалось запустить программу!
		debugfile.WriteLine("Запуск не удался")
		Return
	}
	
	debugfile.Write("После запуска: ")
	GoSub debug_activewindowinfo
	
	Sleep 5000
	MsgBox, 64, Программа1, Программа1 запущена! `nЗдесь вы сможете начать работу с выбранным документом, 5
	
	debugfile.WriteLine("Проверка на экселевский файл: " (Ed_App4 ~= "\.(xls|xlsx|xlsm)$"))
	
	If (Ed_App4 ~= "\.(xls|xlsx|xlsm)$") {
		debugfile.Write("Перед активацией Excel: ")
		GoSub debug_activewindowinfo
		
		WinActivate ahk_exe Excel.exe
		
		debugfile.Write("После активации Excel: ")
		GoSub debug_activewindowinfo
	}
	
	; Ставим окно всегда сверху
	WinGet, debug_exstyle, ExStyle, A
	debugfile.WriteLine("Активное окно поверх всех (перед): " (debug_exstyle & 0x8))
	
	WinSet, AlwaysOnTop, On, A
	
	WinGet, debug_exstyle, ExStyle, A
	debugfile.WriteLine("Активное окно поверх всех (после): " (debug_exstyle & 0x8))
	
	debugfile.Write("Перед выходом: ")
	GoSub debug_activewindowinfo
	Return

debug_activewindowinfo:
	WinGetTitle, debug_title, A
	WinGet, debug_processname, Process, A
	WinGet, debug_processid, Process, A
	debugfile.WriteLine(Format("  Активное окно: заголовок='{1}', процесс: '{2}' ({3})" 
	, debug_title, debug_processname, debug_processid))
	Return

Возможен ли вариант, чтобы при запуске скрипт как-то "убивал" старый процесс Экселя и запускал новый?
Возможен, но желательно ли это? Вдруг у человека там важные данные, с которыми он целый день работал и не успел сохранить?

Code: Select all

; При закрытии может выскочить запрос, хотим ли мы сохранить файл:
WinClose, ahk_exe excel.exe

; Более сурово, безо всяких запросов и сохранений:
Process, Close, excel.exe
github://oGDIp - GDI+ wrapper for AHK v1.1
marusa122
Posts: 135
Joined: 22 Mar 2023, 07:48

Re: Как оставлять окно всегда сверху?

10 May 2023, 11:02

mcl, проверила методом тыка - все-таки первая ваша версия скрипта работает лучше. Единственный момент - при исчезновении стартового Msgbox окно Экселя должно находится поверх остальных окон. Тогда скрипт фиксирует его (именно окно с заданным файлом) на такой позиции. Даже если в Экселе в этот момент открыты другие окна с другими файлами. Если во время исчезновения стартового Msgbox окно с файлом будет свернуто или будет скрыто другими окнами, оно не закрепится поверх остальных окон :crazy: .

Return to “Помощь”

Who is online

Users browsing this forum: No registered users and 2 guests