Что нового

[Окна, Диалоги] Отслеживание событий внешнего окна

killbond

Осваивающий
Сообщения
96
Репутация
32
Имеется некоторое окно, нужно отследить его сворачивание - $GUI_EVENT_MINIMIZE

Код:
#include <GUIConstantsEx.au3>

$sTitle = "AutoIt Help"

While 1
	$avMsg = GUIGetMsg (1)  
	if ($avMsg[1] = WinGetHandle ($sTitle)) AND ($avMsg[0] = $GUI_EVENT_MINIMIZE)  Then
		MsgBox (0, "", $avMsg[1])
	EndIf
	sleep (10)
Wend

По сути, здесь все правильно, однако, не работает, почему?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
killbond сказал(а):
По сути, здесь все правильно, однако, не работает, почему?
Если не работает, значит неправильно. Все функции и константы, которые начинаются на GUI... предназначены для работы со внутренними AutoIt'овскими окнами, созданными с помощью GUICreate(), и не имеют ничего общего с внешними окнами. Для контроля за внешними окнами используй функции, которые начинаются на Win... и Control...
 
Автор
K

killbond

Осваивающий
Сообщения
96
Репутация
32
Код:
$sTitle = "AutoIt Help"

While 1
	if  WinGetState ($sTitle) = 23  Then
		MsgBox (0, "", "")
	EndIf
	sleep (10)
Wend


Но здесь отслеживается факт свернутого окна, а хотелось бы именно событие.
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
killbond
Любопытно, но среди стандартных оконных событий почему-то нет события сворачивания...
Максимально близкими по смыслу стандартными событиями можно считать активацию, создание и уничтожение, и уже в этих событиях проверять состояние нужных окон на свернутость...
Пока других идей нет...

Вот скрипт с оффсайта для размышления...

Код:
#include <SendMessage.au3>
#include <ListBoxConstants.au3>
#include <WindowsConstants.au3>
#include <GuiConstants.au3>
#include <Misc.au3>

#NoTrayIcon
Opt("GUICloseOnESC", 0)
Opt("GUIOnEventMode", 1)
Opt("WinWaitDelay", 0)

;Global Const $WM_SYSCOMMAND = 0x0112
Global Const $SC_MOVE = 0xF010
Global Const $SC_SIZE = 0xF000
Global Const $SC_CLOSE = 0xF060

;ShellHook notification codes:
Global Const $HSHELL_WINDOWCREATED = 1;
Global Const $HSHELL_WINDOWDESTROYED = 2;
Global Const $HSHELL_ACTIVATESHELLWINDOW = 3;
Global Const $HSHELL_WINDOWACTIVATED = 4;
Global Const $HSHELL_GETMINRECT = 5;
Global Const $HSHELL_REDRAW = 6;
Global Const $HSHELL_TASKMAN = 7;
Global Const $HSHELL_LANGUAGE = 8;
Global Const $HSHELL_SYSMENU = 9;
Global Const $HSHELL_ENDTASK = 10;
Global Const $HSHELL_ACCESSIBILITYSTATE = 11;
Global Const $HSHELL_APPCOMMAND = 12;
Global Const $HSHELL_WINDOWREPLACED = 13;
Global Const $HSHELL_WINDOWREPLACING = 14;
Global Const $HSHELL_RUDEAPPACTIVATED = 32772;
Global Const $HSHELL_FLASH = 32774;

Global $bHook = 1
;GUI stuff:

Global $iGuiW = 400, $iGuiH = 50, $sTitle = "Shell Hooker", $aBtnText[2] = ["START", "STOP"]
$hGui = GUICreate($sTitle, $iGuiW, $iGuiH, -1, 0, $WS_POPUP+$WS_BORDER, $WS_EX_TOPMOST)
GUISetOnEvent($GUI_EVENT_CLOSE, "SysEvents")
GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "SysEvents")
GUIRegisterMsg($WM_SYSCOMMAND, "On_WM_SYSCOMMAND")
$cBtnMini = GUICtrlCreateButton("v", $iGuiW-$iGuiH, 0, $iGuiH/2, $iGuiH/2)
GUICtrlSetOnEvent(-1, "CtrlEvents")
GUICtrlSetTip(-1, "Minimize")
$cBtnClose = GUICtrlCreateButton("X", $iGuiW-$iGuiH/2, 0, $iGuiH/2, $iGuiH/2)
GUICtrlSetOnEvent(-1, "CtrlEvents")
GUICtrlSetTip(-1, "Exit")
$cBtnHook = GUICtrlCreateButton("", $iGuiW-$iGuiH, $iGuiH/2, $iGuiH, $iGuiH/2)
GUICtrlSetData(-1, $aBtnText[$bHook])
GUICtrlSetTip(-1, "Hook/Unhook Shell")
GUICtrlSetOnEvent(-1, "CtrlEvents")
$cList = GUICtrlCreateList("", 0, 0, $iGuiW-$iGuiH-1, $iGuiH, $LBS_NOINTEGRALHEIGHT+$WS_VSCROLL)
GUICtrlSetOnEvent(-1, "CtrlEvents")

;Hook stuff:
GUIRegisterMsg(RegisterWindowMessage("SHELLHOOK"), "HShellWndProc")
ShellHookWindow($hGui, $bHook)


GUISetState()

While 1
	Sleep(1000)
WEnd

Func SysEvents()
	Switch @GUI_CtrlId
		Case $GUI_EVENT_CLOSE
			Exit
		Case $GUI_EVENT_PRIMARYDOWN
			;CTRL + Left click to drag GUI
			If _IsPressed("11") Then
				DllCall("user32.dll", "int", "ReleaseCapture")
				DllCall("user32.dll", "int", "SendMessage", "hWnd", $hGui, "int", 0xA1, "int", 2, "int", 0)
			EndIf
	EndSwitch
EndFunc
Func CtrlEvents()
	Switch @GUI_CtrlId
		Case $cBtnMini
			GUISetState(@SW_MINIMIZE)
		Case $cBtnClose
			_SendMessage($hGui, $WM_SYSCOMMAND, $SC_CLOSE, 0)
		Case $cBtnHook
			$bHook = BitXOR($bHook, 1)
			ShellHookWindow($hGui, $bHook)
			GUICtrlSetData($cBtnHook, $aBtnText[$bHook])
	EndSwitch	
EndFunc
Func HShellWndProc($hWnd, $Msg, $wParam, $lParam)
	Switch $wParam
		Case $HSHELL_WINDOWCREATED
			MsgPrint("Window created: " & $lParam & " (" & WinGetTitle($lParam) & ")")
		Case $HSHELL_WINDOWDESTROYED
			MsgPrint("Window destroyed: " & $lParam)
		Case $HSHELL_ACTIVATESHELLWINDOW
			MsgPrint("HSHELL_ACTIVATESHELLWINDOW: Not used.");
		Case $HSHELL_WINDOWACTIVATED
			MsgPrint("Window activated: " & $lParam & " (" & WinGetTitle($lParam) & ")")
		Case $HSHELL_GETMINRECT
			Local $tSHELLHOOKINFO = DllStructCreate("hwnd hwnd;int left;long top;long right;long bottom", $lParam)
			MsgPrint("HSHELL_GETMINRECT: " & HWnd(DllStructGetData($tSHELLHOOKINFO, "hwnd")) & ' (' & _
											DllStructGetData($tSHELLHOOKINFO, "left") & ',' & _
											DllStructGetData($tSHELLHOOKINFO, "top") & ',' & _	
											DllStructGetData($tSHELLHOOKINFO, "right") & ',' & _	
											DllStructGetData($tSHELLHOOKINFO, "bottom") & ')')
		Case $HSHELL_REDRAW
			MsgPrint("Window redraw: " & $lParam & " (" & WinGetTitle($lParam) & ")")
		Case $HSHELL_TASKMAN
			MsgPrint("HSHELL_TASKMAN: Can be ignored.");
		Case $HSHELL_LANGUAGE
			MsgPrint("HSHELL_LANGUAGE: " & $lParam);
		Case $HSHELL_SYSMENU
			MsgPrint("HSHELL_SYSMENU: " & $lParam);
		Case $HSHELL_ENDTASK
			MsgPrint("Window needs to be closed: " & $lParam & " (" & WinGetTitle($lParam) & ")")
		Case $HSHELL_ACCESSIBILITYSTATE
			MsgPrint("HSHELL_ACCESSIBILITYSTATE: " & $lParam);
		Case $HSHELL_APPCOMMAND
			MsgPrint("HSHELL_APPCOMMAND: " & $lParam);
		Case $HSHELL_WINDOWREPLACED
			MsgPrint("Window replaced: " & $lParam & " (" & WinGetTitle($lParam) & ")")
		Case $HSHELL_WINDOWREPLACING
			MsgPrint("Window replacing: " & $lParam & " (" & WinGetTitle($lParam) & ")")
		Case $HSHELL_RUDEAPPACTIVATED
			MsgPrint("HSHELL_RUDEAPPACTIVATED: " & $lParam);
		Case $HSHELL_FLASH
			MsgPrint("Window flash: " & $lParam & " (" & WinGetTitle($lParam) & ")")
		Case Else
			MsgPrint("Unknown ShellHook message: " & $wParam & " , " & $lParam)
	EndSwitch
EndFunc
;register/unregister ShellHook
Func ShellHookWindow($hWnd, $bFlag)
	Local $sFunc = 'DeregisterShellHookWindow'
	If $bFlag Then $sFunc = 'RegisterShellHookWindow'
	Local $aRet = DllCall('user32.dll', 'int', $sFunc, 'hwnd', $hWnd)
	MsgPrint($sFunc & ' = ' & $aRet[0])
	Return $aRet[0]
EndFunc
Func MsgPrint($sText)
	ConsoleWrite($sText & @CRLF)
	GUICtrlSendMsg($cList, $LB_SETCURSEL, GUICtrlSendMsg($cList, $LB_ADDSTRING, 0, $sText), 0)
EndFunc
;register window message
Func RegisterWindowMessage($sText)
	Local $aRet = DllCall('user32.dll', 'int', 'RegisterWindowMessage', 'str', $sText)
	Return $aRet[0]
EndFunc
Func On_WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
    Switch BitAND($wParam, 0xFFF0)
        Case $SC_MOVE, $SC_SIZE
		Case $SC_CLOSE
			ShellHookWindow($hGui, 0)
			Return $GUI_RUNDEFMSG
			;Exit
	EndSwitch
EndFunc
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Но здесь отслеживается факт свернутого окна, а хотелось бы именно событие.
Код:
$Flag = BitAND(WinGetState('AutoIt Help'), 16)

While 1
	If WinExists('AutoIt Help') Then
		$State = BitAND(WinGetState('AutoIt Help'), 16)
		If $State <> $Flag Then
			If $State Then
				ConsoleWrite('Minimized...' & @CR)
			Else
				ConsoleWrite('Restored...' & @CR)
			EndIf
			$Flag = $State
		EndIf
	EndIf
	Sleep(100)
WEnd
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
killbond
Еще нашел вариант на оффсайте...
Скрипт перехватывает событие сворачивания, но использует для этого библиотеку hook.dll (4 КБ)...

Ссылка на тему, где можно скачать библиотеку...

Ссылка на тему, где есть пример скрипта, перехватыващего событие сворачивания...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
snoitaleR [?]
Еще нашел вариант на оффсайте...
Это не регистрирует сворачивание окна, только лишь активацию и деактивацию.
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
Yashied
Прошу прощения...
Ссылку не на тот пример дал...
Исправил...


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

Однако нашел недостаток и в этом варианте...
Окно FAR не отлавливается...
Если я правильно понял, не отлавливаются консольные окна...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
У меня вообще ничего не происходит...
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
Yashied
У меня работает...
Библиотеку hook.dll нужно положить в папку со скриптом...
 
Автор
K

killbond

Осваивающий
Сообщения
96
Репутация
32
snoitaleR
Да, действительно работает, этот вариант даже интереснее, потому что можно написать обработчик для событий внешних окон, вообщем, спасибо!
Вот только не понял одной детали:

Код:
Global $hhCBT = DLLCall("user32.dll","hwnd","SetWindowsHookEx","int",$WH_CBT, "hwnd",$cbtHOOKproc[0],"hwnd",$DLLinst[0],"int",0)

DLLCall(".\hook.dll","int","SetValuesCBT","hwnd",$gui,"hwnd",$hhCBT[0])

GUIRegisterMsg($HCBT_MINMAX,"myCBTfunc")


Вызов функции описан здесь, но каким образом ей передаются параметры?
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
killbond
Я думаю, что все дело в функции SetValuesCBT, которая, как мне кажется, заставляет обработчик CBT направлять в окно $gui не только его собственные события, но и события ото всех окон...
Это предположение...
Если бы глянуть внутрь hook.dll было бы легче разобраться в механизме... :smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 262
Репутация
2 352
Вот простой но рабочий пример используя оконный хук:

Код:
#NoTrayIcon
Opt("WinWaitDelay", 0)

;ShellHook notification codes:
Global Const $HSHELL_GETMINRECT = 5

;Hook stuff:
$aMsg = DllCall('user32.dll', 'int', 'RegisterWindowMessage', 'str', "SHELLHOOK")
GUIRegisterMsg($aMsg[0], "HShellWndProc")
DllCall('user32.dll', 'int', 'RegisterShellHookWindow', 'hwnd', GUICreate(""))

While 1
	Sleep(1000)
WEnd

Func HShellWndProc($hWnd, $Msg, $wParam, $lParam)
	Switch $wParam
		Case $HSHELL_GETMINRECT
			Local $tSHELLHOOKINFO = DllStructCreate("hwnd hwnd;int left;long top;long right;long bottom", $lParam)
			Local $hWindow = HWnd(DllStructGetData($tSHELLHOOKINFO, "hwnd"))
			
			If BitAND(WinGetState($hWindow), 16) Then
				ToolTip('Minimized window event:' & @CRLF & @CRLF & _
					'Window Handle: ' & $hWindow & @CRLF & _
					'Window Title: ' & WinGetTitle($hWindow), _
					0, 0, "HShellWndProc", 1)
				
				Sleep(5000)
				Exit
			EndIf
	EndSwitch
EndFunc
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
CreatoR
У меня функция HShellWndProc() вызывается (и не только при сворачивании), но ToolTip() ничего не выводит на экран при сворачивании окон...
Что бы это значило?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 262
Репутация
2 352
snoitaleR [?]
функция HShellWndProc() вызывается (и не только при сворачивании)
Она вызывается при оконных событиях.


ToolTip() ничего не выводит на экран при сворачивании окон
Странно, а скрипт выходит после сворачивания окна? :smile:
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
CreatoR
Не выходит тоже...
Я думаю, что условие:
Код:
If BitAND(WinGetState($hWindow), 16) Then
не выполняется, но не понимаю, почему...
Пробовал сворачивать OPERA, INFIUM, HANDYCACHE...
От приложения не зависит, наверное...
 
Верх