Что нового

Принудительный фокус для окна

musicstashall

Знающий
Сообщения
322
Репутация
7
Версия AutoIt: 3.3

Описание:
Подскажите, гуру, плиз, как принудительно удержать в фокусе определенное окно?? Если в данный момент открывается несколько окон, мне нужно по очереди обработать каждое, но при этом нужно, чтобы окно было в фокусе, независимо от действий и событий на рабочем столе, даже если непрестанно кликать мышкой и сбивать фокус. Вот, придумываю как-то так, но это не решает задачи:
Код:
Func Activate()
    While 1
	    If WinActive($lParam) = 0 Then
		    WinActivate($lParam)
	    Else
		    Sleep(30)
		    ; выполняем действие для активного окна
		    ExitLoop
	    EndIf
	WEnd
EndFunc
 
A

Alofa

Гость
Почитайте про:
Код:
SendKeepActive()
; и
BlockInput()
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Поэксперементировал:
Код:
WinActivate($lParam)
SendKeepActive($lParam)
MsgBox("", "", "")


В итоге активен MsgBox, а не моё окно.
 
A

Alofa

Гость
musicstashall сказал(а):
Код:
; выполняем действие для активного окна
Код:
; Перед каждым действием выполняйте:
If Not WinActive($lParam) Then WinActivate($lParam)

; И еще почитайте:
WinSetOnTop()
; Но это не спасет от таких окон как:
MsgBox(4096, "", "Системная, поверх всех окон (System modal)")
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Вот так делаю, но все равно некоторые окна «пропадают»:
Код:
Func Activate()
	BlockInput(1)
	For $lparam in $aArray
		WinActivate($lParam)
		$a = @extended
		If $a > 1 Then
		    WinSetOnTop($lParam, "", 1)
		    WinActivate($lParam)
		    Sleep(50)
		    EnableBlurBehind($lparam); выполняем действие
		    WinSetOnTop($lParam, "", 0)
		ElseIf $a = 1 Then
			WinSetOnTop($lParam, "", 1)
			WinActivate($lParam)
			EnableBlurBehind($lparam); выполняем действие
			WinSetOnTop($lParam, "", 0)
		EndIf
		ConsoleWrite("Состояние: " & $a & @CR)
		_ArrayDelete($aArray, $lparam)
	Next
	BlockInput(0)
EndFunc



Добавлено:
Сообщение автоматически объединено:

Параллельно хочу спросить — как предотвратить повторный вызов функции, пока в ней выполняются действия, например For in?
 
A

Alofa

Гость
Я не знаю что вы делаете в "EnableBlurBehind()" - там может быть "Sleep()"-ов штук 100, а за это время фокус может быть где угодно.
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Нет, там задается структура для окраски окон, очень быстро, дольше окно перекрашивается, поэтому я делаю Sleep(50).

Код:
Func EnableBlurBehind($hwnd)
	Const $DWM_BB_ENABLE = 0x00000001
	$Struct = DllStructCreate("dword;int;ptr;int")
	DllStructSetData($Struct, 1, $DWM_BB_ENABLE)
	DllStructSetData($Struct, 2, "1")
	DllStructSetData($Struct, 4, "1")
	DllCall("dwmapi.dll", "int", "DwmEnableBlurBehindWindow", "hwnd", $hwnd, "ptr", DllStructGetPtr($Struct))
EndFunc   ;==>EnableBlurBehind



Добавлено:
Сообщение автоматически объединено:

Если окно получит новую структуру вне фокуса, то оно и окрасится в цвет неактивного окна. В этом всё дело))
 
A

Alofa

Гость
musicstashall сказал(а):
... Если окно получит новую структуру вне фокуса, то оно и окрасится в цвет неактивного окна. В этом всё дело))
OffTopic:
Толи лыжи не едут, толи я... ... эм, вас не понимаю. :smile:

Причем тут?
musicstashall сказал(а):
... окрасится в цвет неактивного окна.
Функция _WinAPI_DwmEnableBlurBehindWindow() (в вашем случае "EnableBlurBehind()") задает подложке окна эффект размытия и ей все равно в каком это окно состоянии.
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Alofa сказал(а):
Функция _WinAPI_DwmEnableBlurBehindWindow() (в вашем случае "EnableBlurBehind()") задает подложке окна эффект размытия и ей все равно в каком это окно состоянии.
Я не разобрался, как конкретно работает эта функция, но она «застекляет» всё тело окна, если используется черная тема. За основу взял GlassCmd. Много чего усовершенствовал, в том числе решаю задачу устранить появление белых окон, которые возникают как раз в следствии обработки в неактивном состоянии. То есть цвет «стекла» делается равным цвету бордюров окна в данный момент. Хорошо бы подойти к этой задаче профессионально и задавать цвет непосредственно, тогда отпала бы необходимость ловить фокус. Кроме того, хотелось бы, чтобы установленный цвет подложки тоже динамично менался, взависимости от фактора активно или не активно, как и бордюры.


Было бы замечательно, если бы можно было непосредственно задавать цвет окнам, независимо от активности окна. Но хотелось бы пойти дальше и динамически изменять цвет тела окна, как он меняется на бордюрах. Если посмотреть на правильно окрашенное окно, когда оно неактивно, то увидим, что его цвет остается статичным, не повторяет цвета бордюра:

Скрипт, как всё было организовано изначально:
Код:
#include <Misc.au3>
#include <Process.au3>
#include <WinAPI.au3>

Global Const $HSHELL_WINDOWCREATED = 1
Global Const $HSHELL_WINDOWACTIVATED = 4
Global Const $HWND_MESSAGE = -3
Global $bHook = 1

$hGui = GUICreate("", 10, 10, -1, 0, -1, -1, $HWND_MESSAGE)
GUIRegisterMsg(_WinAPI_RegisterWindowMessage("SHELLHOOK"), "HookProc")
ShellHookWindow($hGui, $bHook)

Func hookproc($hwnd, $msg, $wparam, $lparam)
	Switch $wparam
		Case $HSHELL_WINDOWCREATED, $HSHELL_WINDOWACTIVATED
			; здесь «ловим» окно
                        EnableBlurBehind($lparam) ; «застекляем» по условию
	EndSwitch
EndFunc   ;==>hookproc

Func EnableBlurBehind($hwnd)
	Const $DWM_BB_ENABLE = 0x00000001
	$Struct = DllStructCreate("dword;int;ptr;int")
	DllStructSetData($Struct, 1, $DWM_BB_ENABLE)
	DllStructSetData($Struct, 2, "1")
	DllStructSetData($Struct, 4, "1")
	DllCall("dwmapi.dll", "int", "DwmEnableBlurBehindWindow", "hwnd", $hwnd, "ptr", DllStructGetPtr($Struct))
EndFunc   ;==>EnableBlurBehind

Func ShellHookWindow($hwnd, $bFlag)
	Local $sFunc = 'DeregisterShellHookWindow'
	If $bFlag Then $sFunc = 'RegisterShellHookWindow'
	Local $aRet = DllCall('user32.dll', 'int', $sFunc, 'hwnd', $hwnd)
	Return $aRet[0]
EndFunc   ;==>ShellHookWindow


Добавлено:
Сообщение автоматически объединено:

Читаю связные темы, но пока очень далек от представления:
Код:
_WinAPI_DwmGetColorizationColor
_WinAPI_DwmEnableBlurBehindWindow
 
Верх