1

Тема: AHK: обтекание определенного окна Windows другими окнами

Есть окно программы (назовем №1), которое всегда должно быть на виду, а также не загораживать другие окна. Т.е. другие окна должны просто обтекать окно №1.
Возможно ли такое реализовать с помощью AHK?
P.S. Нашел скрипт который делает окно всегда поверх других окон:

^+SPACE:: Winset, Alwaysontop, , A

Но это не то. Т.к. когда открываются новые окна - окно №1 загораживает их, и приходится изменять положение  и размер у каждого нового открытого окна. А в процессе работы их открываются много.

2

Re: AHK: обтекание определенного окна Windows другими окнами

Вы можете перемещать любые окна и изменять их размер с помощью команды WinMove.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK: обтекание определенного окна Windows другими окнами

teadrinker для начал мне надо разобраться с алгоритмом. Вот что я пока придумал:

-Получить координаты и размер активного окна №1 (которое все остальные должны обтекать)
цикл (пока работает скрипт) {
	- Получить список всех других открытых окон
	- Задать для них координаты(переместить), не входящие в область, покрывающую окно №1
	- Пауза на 500 мс
}

Однако я думаю может есть вариант по-проще, не заставляющий скрипт мониторить все окна каждые 500мс? Вдруг это будет нагружать осн. систему?
Мне интересно по такому же принципу написан код раб.стола Windows? Ведь окна не заходят ниже Панели задач, где меню Пуск. Панель их ограничивает, и они ее обтекают. Причем если панель не закреплена, можно изменить ее ширину и доступная область для окон сужается. Разработчики ОС так же все делали?
Я лишь начинающий в программировании, подскажите как лучше сделать?

4

Re: AHK: обтекание определенного окна Windows другими окнами

Если хотите поймать момент появления новых окон, существует специальный хук для этого, даже несколько. Попозже смогу провести пример.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5

Re: AHK: обтекание определенного окна Windows другими окнами

teadrinker этот хук будет производиться средствами AHK?
Дело в том, что админы у нас на работе ограничили возможности системы Windows для сотрудников. Я и так очень удивился, когда увидел что можно пользоваться AutoHotKey. Ну она наверно безобидная для системы.
В любом случае подскажите пожалуйста что за хук, а там посмотрим, может и он будет работать))

6

Re: AHK: обтекание определенного окна Windows другими окнами

mike.sunday19 пишет:

другие окна должны просто обтекать

Какое-то новое выражение. Это как? Можно пример в виде картинки?

7 (изменено: mike.sunday19, 2021-09-25 14:59:43)

Re: AHK: обтекание определенного окна Windows другими окнами

ypppu, Слово "Обтекают" я взял из Worda. Там когда вставляешь картинку, в ее форматировании есть способ "обтекания текста" вставленной картинки. По тому же принципу я хочу чтобы работали все окна относительно главного окна.
Ладно, тогда покажу в картинке. Выкладываю пример. В примере окном, которое должно всегда быть на виду и не мешать другим окнам - это окно Блокнот.
P.S. мда пожалуй в приведенном раньше примере панели управления меню Пуск я немного затупил. Окна ее не обтекают, они также заходят за нее.

Post's attachments

2021-09-25_134650.jpg 257.11 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

8

Re: AHK: обтекание определенного окна Windows другими окнами

Перефразирую. Надо чтобы другие окна не могли переходить границу целевого окна.
Только тогда не понятно, что будет, если целевое окно появилось позже всех, и при этом произошло наложение. Оно должно раздвинуть соседние окна? И такой же вопрос - что будет, если целевое окно растягивать мышкой. Оно должно расталкивать остальные окна или упереться в них?

9 (изменено: mike.sunday19, 2021-09-25 15:58:35)

Re: AHK: обтекание определенного окна Windows другими окнами

ypppu пишет:

Перефразирую. Надо чтобы другие окна не могли переходить границу целевого окна.

все верно.

ypppu пишет:

Только тогда не понятно, что будет, если целевое окно появилось позже всех, и при этом произошло наложение. Оно должно раздвинуть соседние окна? И такой же вопрос - что будет, если целевое окно растягивать мышкой. Оно должно расталкивать остальные окна или упереться в них?

Если честно так далеко я не задумывался . Сейчас думая об этом, чтобы сделать все проще - может просто выделить прямоугольную область в левом верхнем углу, в которую запрещен доступ всем окнам, кроме целевого? Можно даже выделить ее рамкой. Туда буду помещать целевое окно и вручную погнонять его размер под рамку. А изменять размеры рамки, если вдруг понадобится можно через параметры length и width при редактировании скрипта.
Однако если до включения скрипта в этой области были окна - надо все-таки чтобы рамка раздвинула эти окна.
Да, тогда все упрощается. Как вам идея?

10

Re: AHK: обтекание определенного окна Windows другими окнами

Вот так можно отследить возникновение нового окна и переместить его сразу куда-нибудь:

DllCall("RegisterShellHookWindow", Ptr, A_ScriptHwnd) 
OnMessage(DllCall("RegisterWindowMessage", Str, "SHELLHOOK"), "ShellProc") 
OnExit("Exit")
Return

ShellProc(nCode, hWnd) {
   static HSHELL_WINDOWCREATED := 1
   if (nCode = HSHELL_WINDOWCREATED) {
      WinMove, ahk_id %hWnd%,, 100, 100
   }
}

Exit()  {
   DllCall("DeregisterShellHookWindow", Ptr, A_ScriptHwnd)
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11

Re: AHK: обтекание определенного окна Windows другими окнами

teadrinker спасибо большое за код, очень помогли.
Однако я пытался доработать, чтобы изменять положение и размер окон по нажатию горячих клавиш, и у меня возникли проблемы с браузером Internet Explorer. Окна всех остальных приложений вроде изменяются как надо. А вот IE тупит. Вроде он изменился, но вот зайти в него после выполненного действия над ним, не могу.
Подскажите пожалуйста в чем проблема.
Выкладываю код:


#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.


;Получить размеры рабочей области экрана
getMonitor(){
	Array := Array()
	SysGet, Monitor, Monitor, 1
	SysGet, MonitorWorkArea, MonitorWorkArea, 1
	WinGetPos,,,_w_, _h_, ahk_class Shell_TrayWnd   ;получить размеры панели управления
	
	Array.1 := MonitorWorkAreaRight
	Array.2 := MonitorBottom - _h_
	
	return Array
}	

;Ширина и высота изначально рабочей области экрана
Array := Array()
Array := getMonitor()
global scrWorkArea_w := Array.1
global scrWorkArea_h := Array.2

;Ширина и высота рамки блокируемой области
global frame_w := 500		
global frame_h := 200



;Включить отслеживание открытия нового окна
DllCall("RegisterShellHookWindow", Ptr, A_ScriptHwnd) 
OnMessage(DllCall("RegisterWindowMessage", Str, "SHELLHOOK"), "ShellProc") 
OnExit("Exit")
Return

ShellProc(nCode, hWnd) {
   static HSHELL_WINDOWCREATED := 1
   if (nCode = HSHELL_WINDOWCREATED) {
		;Sleep, 5000
		cX := frame_w + 1
		cY := 0
		WinMove, ahk_id %hWnd%,, cX, cY, scrWorkArea_w - frame_w - 1, scrWorkArea_h
   }
}

Exit()  {
   DllCall("DeregisterShellHookWindow", Ptr, A_ScriptHwnd)
}

^3::
	WinGet, id, list,,, Program Manager
	Loop, %id% {
		this_id := id%A_Index%
		
		WinGetPos, X, Y, , , ahk_id %this_id%
		if((X<frame_w)and(Y<frame_h)){
			WinGet, WinStatus, MinMax, ahk_id %this_id%
			WinGetClass, this_class, ahk_id %this_id%
			if (WinStatus != 0)
				WinRestore, ahk_id %this_id%
			cX := frame_w + 1
			cY := 0

			WinMove, ahk_id %this_id%,, cX, cY, scrWorkArea_w - frame_w - 1, scrWorkArea_h
		}
	}
return

12

Re: AHK: обтекание определенного окна Windows другими окнами

У интернет эксплорера есть сразу несколько отдельных окон, можете отследить их так:

Run iexplore.exe
WinWait, ahk_class IEFrame
Sleep, 3000
WinGet, id, list, ahk_exe iexplore.exe
Loop, %id% {
   this_id := id%A_Index%
   WinGetClass, this_class, ahk_id %this_id%
   WinGetTitle, title, ahk_id %this_id%
   MsgBox, % "title: " . title . "`nclass: " . this_class
}

Точно не знаю почему, но манипуляции с этими окнами, кроме главного, и приводят к такому результату.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13

Re: AHK: обтекание определенного окна Windows другими окнами

teadrinker,  Вообщем отследить их смог, но было куча мороки, долго игрался чтобы они корректно видоизменялись.
Наконец-то закончил весь код:


#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

;список окон IE. 
global My_Array := Array()

;id целевого окна (ОБТЕКАЕМОГО)
global mainWinId := 0

;Получить размеры рабочей области экрана
getMonitor(){
	cArray := Array()
	SysGet, Monitor, Monitor, 1
	SysGet, MonitorWorkArea, MonitorWorkArea, 1
	WinGetPos,,,_w_, _h_, ahk_class Shell_TrayWnd   ;получить размеры панели управления
	
	cArray.1 := MonitorWorkAreaRight
	cArray.2 := MonitorBottom - _h_
	
	return cArray
}	

;Ширина и высота изначально рабочей области экрана
c_Array := getMonitor()
global scrWorkArea_w := c_Array.1
global scrWorkArea_h := c_Array.2

;Ширина и высота рамки блокируемой области
global frame_w := 500		
global frame_h := 200

;проверяем является ли окном IE
Check_id(id_old){
	ch := false
	for index, element in My_Array
	{
		if(id_old == element){
			ch := true
		}
	}
	return ch
}

;двигаем все окна кроме целевого
moveOrdWin(){
	
	;обрабатываем окна IE
	IfWinExist, ahk_class IEFrame        
	{
		WinGet, id, list, ahk_exe iexplore.exe
		Loop, %id% {
			this_id := id%A_Index%
			My_Array.Push(this_id)			;добавляем в список окон IE. Окна IE надо обрабатывать отдельно от др. окон
			if(this_id != mainWinId){
				WinGetPos, X, Y, , , ahk_id %this_id%
				if((X<frame_w)and(Y<frame_h)){			;если находится в блокируемой области 
					WinActivate, ahk_id %this_id%
					SysGet, m1, Monitor, 1
					
					;у IE окна не только класса IEFrame, поэтому надо 2 раза фигачить WinMove на всякий случай
					WinMove, ahk_class IEFrame,, frame_w+1, 0, scrWorkArea_w-frame_w-1, scrWorkArea_h
					WinMove,,, frame_w+1, 0, scrWorkArea_w-frame_w-1, scrWorkArea_h	
					
				}
			}
		}
	}
	
	;обрабатываем все остальные окна 
	WinGet, id, list,,, Program Manager
	Loop, %id% {
		this_id := id%A_Index%
		if(this_id != mainWinId){
			go := Check_id(this_id)
			if(go == false){			;проверяем если не окно IE
				WinGetPos, X, Y, , , ahk_id %this_id%
				if((X<frame_w)and(Y<frame_h)){				
					WinGet, WinStatus, MinMax, ahk_id %this_id%
					if (WinStatus != 0)
						WinRestore, ahk_id %this_id%
					WinMove, ahk_id %this_id%,, frame_w+1, 0, scrWorkArea_w-frame_w-1, scrWorkArea_h	
				}
			}
		}
	}
}

;Включить отслеживание открытия нового окна
DllCall("RegisterShellHookWindow", Ptr, A_ScriptHwnd) 
OnMessage(DllCall("RegisterWindowMessage", Str, "SHELLHOOK"), "ShellProc") 
OnExit("Exit")
Return

ShellProc(nCode, hWnd) {
   static HSHELL_WINDOWCREATED := 1
   if (nCode = HSHELL_WINDOWCREATED) {
		cX := frame_w + 1
		cY := 0
		WinGetClass, this_class, ahk_id %hWnd%
		if(this_class != "#32770")
			WinMove, ahk_id %hWnd%,, frame_w+1, 0, scrWorkArea_w - frame_w - 1, scrWorkArea_h
   }
}

Exit()  {
   DllCall("DeregisterShellHookWindow", Ptr, A_ScriptHwnd)
}

;Включаем целевое окно
^+1:: 
	if(mainWinId == 0){
		WinGet, active_id, ID, A
		mainWinId := active_id
		WinGet, WinStatus, MinMax, ahk_id %active_id%
		if (WinStatus != 0)
			WinRestore, ahk_id %active_id%
		WinMove, ahk_id %active_id%,, 0, 0, frame_w, frame_h
		Winset, Alwaysontop, , ahk_id %active_id%
		moveOrdWin()
	} else {
		WinGetTitle, Title, ahk_id %mainWinId%
		MsgBox, Прежде выключите целевое окно: %Title%
	}
	
return

;Выключаем целевое окно
^+2:: 
	WinGet, active_id, ID, A
	if(mainWinId = active_id){
		mainWinId := 0
		Winset, Alwaysontop, , ahk_id %active_id%
	}
return

;двигаем все окна, кроме целевого
^3::moveOrdWin()

От идеи мониторинга перемещения всех окон отказался. Боюсь что будет грузить систему если он каждую секунду будет прозванивать десяток окон. Сделал передвижение окон по кнопке.

И еще, почему-то IE отказывается быть целевым окном. Я вроде добавляю его id в исключение(чтобы только его не видоизменять), а он каким-то образом после этого плодит себе копию с другим id. Фиг его знает что не так с этим IE.
Ну, мне всеравно, мне для работы надо чтобы Excel всегда был на виду. Работает - и это главное.

teadrinker, спасибо еще раз за помощь! Тему можно закрывать