Что нового

Как отследить появление окна (IE например)?

Ocago

Новичок
Сообщения
35
Репутация
0
Доброго времени суток :smile:
Где-то встречал тут тему с использованием оконного хука - но там был пример отслеживания события минимизации окна (любого приложения, в частности и IE)

А как несложными методами организовать отслеживание именно появления нового окна? Если известно только название приложения (ну, или ехе файл, его вызывающий).

Всем спасибо за любые идеи.
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Re: Как отследить появления окна (IE например)?

Ocago
Если нужно, чтобы скрипт ждал нужное окно, то потребуется функция WinWait()...
Если желательно, чтобы скрипт не приостанавливал работу, то можно использовать в цикле обработки сообщений вызов функции WinExists()...
Также потребуется утилита AU3INFO.EXE для определения характеристик окна, чтобы максимально точно его идентифицировать...
 

aranea

Новичок
Сообщения
31
Репутация
4
Re: Как отследить появления окна (IE например)?

Если известно только название приложения
Я бы использовал
Код:
ProcessWait("iexplore.exe")


Или если постоянно ожидать процесс, то вот пример взятый с форума, чей не помню
Код:
Local $iPID
While 1
    $iPID = ProcessExists('iexplore.exe')
    If $iPID Then
        ; код че далать когда процесс появился
        ExitLoop
    EndIf
    Sleep(500)
WEnd
 
Автор
O

Ocago

Новичок
Сообщения
35
Репутация
0
Re: Как отследить появления окна (IE например)?

Идея понятна вроде.. спасибо, попробую..

Тут правда нюанс - скажем, уже есть процесс рабочий iexplore.exe - и ожидаются новые (IE под каждое окно свой процесс открывает). Как тут быть?

Видимо там внутри цикла ожидания нужно массив организовывать? Чтобы при появлении каждого нового процесса, идентифицировать окно его по Hаndle и присваивать ему значение (WinSetState($hIEFrame, "", @SW_HIDE)).... как то так?

И этот цикл весь вначале скрипта вставлять?


Не слишком будет заморочено?
Я почему через события и подумал, что можно.. Событие - появление окна нового у этого процесса.
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Ocago
Насколько я понял из эксперимента, который провел, IEXPLORE.EXE (версия 6) может создать новое окно без создания нового процесса, поэтому контроль только процессов не эффективен... Понадобится функция WinList() и класс окон IEXPLORE.EXE - IEFrame...

Код:
; НАЧАЛО

 #Include <Array.au3>

 $W=WinList("[CLASS:IEFrame]")
 $N=Ubound($W)

 While True
  $W=WinList("[CLASS:IEFrame]")
  If Ubound($W)<>$N Then
   ;Изменилось количество окон
   $N=Ubound($W)
   _ArrayDisplay($W)
  EndIf
 WEnd

; КОНЕЦ
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Ocago
Можно еще так попробовать с проверкой разрешенной ссылки:
Код:
#include <IE.au3>

Opt("TrayMenuMode", 1);не реагировать на щелчки мышкой по икноке в трее

HotKeySet("+{ESC}", "_Exit") ;Shift+Esc - выход по горячим клавишам
$sUrl = 'http://autoit-script.ru/' ;задаем адрес для проверки
_IECreate($sUrl) ;открываем в IE $sUrl
While 1 ;запускаем бесконечный цикл
	$aListIE = WinList('[Class:IEFrame]') ;получаем массив окон IE
	If $aListIE[0][0] > 1 Then ;если есть больше одного окна IE
		Dim $aListIE_Ex[1][3] ;создаем расширенный массив окон IE
		For $i = 1 To UBound($aListIE) - 1
			ReDim $aListIE_Ex[UBound($aListIE_Ex) + 1][3]
			$aListIE_Ex[$i][0] = $aListIE[$i][0] ;заголовок окна IE
			$aListIE_Ex[$i ][1] = $aListIE[$i][1] ;хэндл окна IE
			$oIE = _IEAttach($aListIE[$i][1], 'HWND')
			$aListIE_Ex[$i][2] = _IEPropertyGet($oIE, "locationurl") ;адрес окна IE
			If Not StringInStr($aListIE_Ex[$i][2], $sUrl) Then ;если в адресе нет строки $sUrl
				WinClose($aListIE_Ex[$i][1]) ; то закрываем это окно IE
				;_IEQuit($oIE) ;так тоже можно закрыть
			EndIf
		Next
	EndIf
	Sleep(1000) ;задаем паузу между проверками в 1 секунду
WEnd

Func _Exit()
	Exit
EndFunc   ;==>_Exit
 
Автор
O

Ocago

Новичок
Сообщения
35
Репутация
0
Спасибо за примеры - сейчас буду пробовать :smile:
Но, навскидку - везде требуются паузы и постоянное выполнение цикла, что не совсем хорошо видимо.
Пауза даст окну появится, "блымкнуть" хоть на секунду.
А постоянный цикл дополнительно озадачит процессор и память (наверное).

В идеале именно через хук решается вопрос. Вот этот скорее всего HSHELL_WINDOWCREATED.
Хуки-же как раз перехватывают события - и этот перехватит появление нового окна (и этому окну можно сразу установить параметры до его появления на экране). Но как эти хуки использовать? Что-то пока не вкурю. :-\

Вот нашёл примерчик использования хука, но это отслеживание минимизации окна (любого) HSHELL_GETMINRECT - работает отлично.
Код:
#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")
GUIRegisterMsg($aMsg[0], "HShellWndProc2")
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


А вот как-бы что-то подобное с HSHELL_WINDOWCREATED сделать - может есть идеи или опыт у кого?
 
Автор
O

Ocago

Новичок
Сообщения
35
Репутация
0
спасибо, посмотрю сейчас..

А с циклами - точно не пойдёт, к сожалению - меньше 1 сек задержку нельзя ставить - не определяются параметры окна.. нестабильно работает.. А 1 сек - это окно показывается.
С такой задержкой и без циклов можно..


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

snoitaleR сказал(а):

Кстати, таки да - это оно :smile: Совсем близко.
Перехватывает сразу любое окно и выводит Title
Теперь-бы как-то там сразу умудриться задать параметры этому окну..
так-же через этот хук.. :-\
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Ocago
На сколько мне известно, не рекомендуется нагружать функцию обработки событий (сообщений) длительной работой, но установка параметров окна, думаю, достаточно быстрый процесс...
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Ocago
Следующий скрипт у меня закрывает любое второе окно IE, при этом памяти кушает чуть больше 5 Мб, процессор не грузит совсем.
Код:
Opt("TrayMenuMode", 1)

HotKeySet("+{ESC}", "_Exit") ;Shift+Esc - выход

While 1
	If WinExists('[Class:IEFrame]') Then
		$hHandleIE_First = WinGetHandle('[Class:IEFrame]')
	EndIf
	While 1
		If WinExists('[Class:IEFrame]') Then
			$hHandleIE_Next = WinGetHandle('[Class:IEFrame]')
			If $hHandleIE_Next <> $hHandleIE_First Then WinClose($hHandleIE_Next)
		Else
			ExitLoop
		EndIf
		Sleep(5)
	WEnd
	Sleep(5)
WEnd

Func _Exit()
	Exit
EndFunc   ;==>_Exit
 
Автор
O

Ocago

Новичок
Сообщения
35
Репутация
0
madmasles сказал(а):
Ocago
Следующий скрипт у меня закрывает любое второе окно IE, при этом памяти кушает чуть больше 5 Мб, процессор не грузит совсем.

ДА, действительно - Отслеживает и прикрывает второе окно. Небольшая нестабильность есть, если вторая старница открывается жабой (кликом по ссылке c обработкой window.open) - пишет ошибку жабы иногда.
Ну, и главный недостаток остался пока - окно "блымкает" (на долю секунды видно его).
А так в целом довольно универсальный вариант, спасибо :smile: Я чуть подкорректировал под свои нужды (окно в HIDE переходит, а не закрывается):
Код:
Opt("TrayMenuMode", 1)

HotKeySet("+{ESC}", "_Exit") ;Shift+Esc - выход

While 1
	If WinExists('[Class:IEFrame]') Then
		$hHandleIE_First = WinGetHandle('[Class:IEFrame]')
	EndIf
	While 1
		If WinExists('[Class:IEFrame]') Then
			$hHandleIE_Next = WinGetHandle('[Class:IEFrame]')
			If $hHandleIE_Next <> $hHandleIE_First Then 

            WinSetState($hHandleIE_Next, "", @SW_HIDE)

		Else
		ExitLoop
		EndIf
		Sleep(5)
	WEnd
	Sleep(5)
WEnd

Func _Exit()
	Exit
EndFunc   ;==>_Exit




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

А вот, кстати альтернатива, работающая через хук (спасибо snoitaleR за наводку):
Код:
#Include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global $hForm

$hForm = GUICreate('')
GUIRegisterMsg(_WinAPI_RegisterWindowMessage('SHELLHOOK'), '_ShellHookProc')
_WinAPI_RegisterShellHookWindow($hForm)

While 1
    Sleep(100)
WEnd

Func _ShellHookProc($hWnd, $iMsg, $wParam, $lParam)
    Switch $hWnd
        Case $hForm
            Switch $wParam
                Case $HSHELL_WINDOWCREATED
                    
					WinSetState(WinGetTitle($lParam), "", @SW_HIDE)
                    
					Local $Title = WinGetTitle($lParam)
                                        If IsString($Title) Then
					    ConsoleWrite('Activated: ' & $Title & @CR)
					EndIf
					
					
            EndSwitch
    EndSwitch
EndFunc   ;==>_ShellHookProc

Func OnAutoItExit()
    _WinAPI_DeregisterShellHookWindow($hForm)
EndFunc   ;==>OnAutoItExit


Не совсем ещё тут всё понятно, но WinSetState(WinGetTitle($lParam), "", @SW_HIDE) - отрабатывает очень быстро и любое окно, любой программы.
Всё равно "блымкает", конечно, но уж очень быстро.

Теперь-бы разобраться что тут поубирать лишнего и корректно закрывать после выполнения основной процедуры. :wacko:

И может где-то тут указать можно ещё раньше параметры окна?
Если кто прокомментирует тут строки хотя-бы - огромное спасибо :smile:
 
Верх