Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   Как дождаться РЕАЛЬНОГО появления окна (http://forum.oszone.net/showthread.php?t=161802)

NewOLDi 29-12-2009 10:57 1306780

Как дождаться РЕАЛЬНОГО появления окна
 
Здравствуйте!

Как дождаться РЕАЛЬНОГО появления окна, т.е. - его полной отрисовки?

Дело в том, что мне нужно поочерёдно открыть несколько окон, очерёдность эта строгая, т.е. на панели задач Windows окна должны располагаться в указанной последовательности. Но одно из окон (приложение) может долго загружаться, в итоге - AutoIt видит окно всеми возможными функциями (я все проверки уже перепробовал) и передаёт управление на запуск следующего окна (приложения), которое запускается гораздо быстрее и становится на панели задач первым, т.к. первое окно хоть и появилось для AutoIt, но реально не отрисовалось!

Паузы использовать не вариант, т.к. окно может запускаться и 2 и 3 и 10 секунд, в зависимости от загруженности системы и прочих составляющих.

ЗЫ: Не смог этот недостаток автоматизаторов побороть в nnCron, теперь не могу и в AutoIt (а он мне значительно больше нравится).

Спасибо.

kaster 29-12-2009 12:32 1306845

Попробуй
Код:

WinWaitNotActive

NewOLDi 29-12-2009 12:58 1306870

К сожалению, это тоже не работает :(

Creat0R 29-12-2009 15:10 1306977

Пример ожидания окна в панели задач:

Код:

#include <GUIToolbar.au3>

$iRet = _WinWaitOnTaskBar("Some window text or Handle", "", 5)

MsgBox(64, 'Return', $iRet)

Func _WinWaitOnTaskBar($sTitle, $sText="", $iWait=0)
    Local $hWinWait = WinWait($sTitle, $sText, $iWait)
    If Not $hWinWait Then Return $hWinWait

    Local $hToolbar = ControlGetHandle("[CLASS:Shell_TrayWnd]", "", "ToolbarWindow322")
    Local $aWinList, $iToolbarButtonIndex, $iTimer = TimerInit()

    While 1
        $aWinList = WinList()

        For $i = 0 To $aWinList[0][0] Step 1
            If Not BitAND(WinGetState($aWinList[$i][1]), 2) Then ContinueLoop

            $iToolbarButtonIndex = _WinAPI_FindToolbarButton($aWinList[$i][1], $hToolbar)

            If $iToolbarButtonIndex > 0 And $aWinList[$i][1] = $hWinWait Then Return $aWinList[$i][1]
        Next

        If $iWait > 0 And TimerDiff($iTimer)/1000 >= $iWait Then Return 0
        Sleep(10)
    WEnd

    Return 0
EndFunc

Func _WinAPI_FindToolbarButton($hWnd, $hTB)
    Local $iReturn = -1, $iPID, $hProcess, $sStruct = DllStructCreate("ptr")

    ; open process owning toolbar control
    _WinAPI_GetWindowThreadProcessId($hTB, $iPID)

    $hProcess = _WinAPI_OpenProcess(0x410, False, $iPID)

    If $hProcess Then
        Local $iCount = _GUICtrlToolbar_ButtonCount($hTB)

        For $i = 0 To $iCount - 1
            Local $iID = _GUICtrlToolbar_IndexToCommand($hTB, $i)

            ; button param is ptr to owner's window handle, stored in target process's memory space
            Local $dwData = _GUICtrlToolbar_GetButtonParam($hTB, $iID)

            ; read the window handle from the explorer process
            Local $aRet = DllCall("kernel32.dll", "int", "ReadProcessMemory", "ptr", _
                $hProcess, "ptr", $dwData, "ptr", DllStructGetPtr($sStruct), "uint", 4, "uint*", 0)

            If $aRet[5] Then
                If $hWnd = DllStructGetData($sStruct, 1) Then
                    $iReturn = $i
                    ExitLoop
                EndIf
            EndIf
        Next

        _WinAPI_CloseHandle($hProcess)
    EndIf

    Return $iReturn
EndFunc


Creat0R 29-12-2009 15:26 1306993

Вариант по проще, но не очень надёжный (в случае если на панели задач будут похожие по названию окна)...

Код:

#include <GUIToolbar.au3>

$iRet = _WinWaitOnTaskBar("Some window text or Handle", 10)

MsgBox(64, 'Return', $iRet)

Func _WinWaitOnTaskBar($sTitle, $iWait=0)
    Local $hTaskBar = ControlGetHandle("[CLASS:Shell_TrayWnd]", "", "ToolbarWindow322")
    Local $iTimer = TimerInit()
    Local $iButton_Count, $sWin_Title

    If IsHWnd($sTitle) Then $sTitle = WinGetTitle($sTitle)

    While 1
        $iButton_Count = _GUICtrlToolbar_ButtonCount($hTaskBar)

        For $i = 1 To $iButton_Count - 1 Step 2
            $sWin_Title = _GUICtrlToolbar_GetButtonText($hTaskBar, _GUICtrlToolbar_IndexToCommand($hTaskBar, $i))
            If WinGetTitle($sWin_Title) = $sTitle Then Return 1
        Next

        If $iWait > 0 And TimerDiff($iTimer)/1000 >= $iWait Then Return 0
        Sleep(10)
    WEnd

    Return 0
EndFunc


NewOLDi 30-12-2009 09:44 1307419

Цитата:

Цитата Creat0R
Пример ожидания окна в панели задач: »

Спасибо, код работает. Но громоздкий он конечно по самое не балуй.

Странно, что такой весь из себя универсальный AutoIt не содержит специальных функций для лёгкого отслеживания реальных открытий окон (их полной отрисовки на экране), ведь архиполезная возможность, паузы (т.е. - пальцем в небо) тогда вообще не нужны во многих ситуациях!

И ещё 2 вопроса по теме...

1:
Во многих оконных функциях AutoIt нельзя использовать в качестве заголовка отрывок текста, ведь заголовок может быть всегда разным, но, в тоже время, всегда с одной и той же припиской (например: Google - Mozilla Firefox или Яндекс - Mozilla Firefox). Есть какая-то лёгкая возможность обходить этот недостаток (к примеру - шаблон, типа: *Mozilla Firefox)? Или спасёт только [CLASS:MozillaWindowClass]? Но последнее не работает в твоём коде, Creat0R, только полный и точный заголовок окна.

2:
Есть сторонние утилиты, которые располагают кнопки (запущенные приложения) на панели задач в нужной последовательности, т.е. Windows это позволяет. Вероятно, что и через AutoIt это можно как-то сделать. Быть может это будет проще, нежели использовать огромный код от Creat0R? Ведь это тоже решение проблемы, хоть и не такое правильное, как хотелось бы изначально.

Спасибо.

Creat0R 30-12-2009 10:30 1307450

Цитата:

Цитата NewOLDi
громоздкий он конечно по самое не балуй »

:o Это далеко не громоздкий пример, есть намного хуже, и казалось бы для более простых задач.

Цитата:

Цитата NewOLDi
Во многих оконных функциях AutoIt нельзя использовать в качестве заголовка отрывок текста »

Как раз совсем обратное верно - во всех оконных функциях можно использовать часть заголовка окна, за это отвечает Opt("WinTitleMatchMode", ...).

Цитата:

Цитата NewOLDi
Или спасёт только [CLASS:MozillaWindowClass]? »

Это оптимальный вариант.

Цитата:

Цитата NewOLDi
последнее не работает в твоём коде, Creat0R, только полный и точный заголовок окна »

Поправил.
Цитата:

Цитата NewOLDi
Есть сторонние утилиты, которые располагают кнопки (запущенные приложения) на панели задач в нужной последовательности, т.е. Windows это позволяет. Вероятно, что и через AutoIt это можно как-то сделать. »

Можно вроде, это всего лишь кнопки, и их можно сдвинуть, но я бы не стал этого делать.

Iska 30-12-2009 12:34 1307522

NewOLDi, Вы бы привели свой код, а то я что-то подозреваю, что дело не в AutoIt, а в особенностях конкретного приложения и в Вашем коде.

NewOLDi 25-01-2010 14:32 1329387

Прошу прощения за длительное отсутствие...

Я всё-таки сам нашёл ПРОСТОЕ и ТОЧНОЕ решение по сабжу, ибо код от Creat0R слишком уж сильно выходит за все мыслимые пределы для такой элементарной задачи.

Итак, если нужно дождаться РЕАЛЬНОГО появления окна (РЕАЛЬНОЙ отрисовки окна) - использовать нужно следующий код:
Код:

While NOT BitAND ( WinGetState ( 'title' ), 2 )
    Sleep ( delay )
WEnd

Я искренне верил, что должна быть в AutoIt встроенная штатная функция, которая способна решить сабж, ВЕДЬ ЭТО ТАК ОЧЕВИДНО! И она есть, вот только не сразу я её углядел, к сожалению.

Да, кстати... Благодарю за AutoItSetOption ( 'option', param ). Полезная фича, не знал :)

Спасибо!

Creat0R 25-01-2010 14:43 1329400

Цитата:

Цитата NewOLDi
нашёл ПРОСТОЕ и ТОЧНОЕ решение по сабжу, ибо код от Creat0R слишком уж сильно выходит за все мыслимые пределы для такой элементарной задачи »

Я писал этот код исходя из вашего утверждения, что окно должно отрисоваться на панели задач. А найдены вами код проверяет окно на "видимость", т.е пока окно не имеет аттрибута "видимое", цикл продолжается.

Если вам нужно было вот такое простое решение, то и задачу нужно было по проще отрисовывать!

NewOLDi 25-01-2010 14:55 1329410

Цитата:

Как дождаться РЕАЛЬНОГО появления окна, т.е. - его полной отрисовки?
Куда уж проще :)

Про панель задач - это чтобы задача была ясна наверняка (на все 200%)..

Creat0R 25-01-2010 15:08 1329419

Цитата:

Цитата NewOLDi
Куда уж проще »

«Как дождаться появление окна, т.е его видимости на экране.»

Цитата:

Цитата NewOLDi
Про панель задач - это чтобы задача была ясна наверняка »

Ну вот как раз этим то задача и была немного сбита с пути.

SharkyEXE 03-11-2019 12:13 2894556

Всем здравствуйте.

Скажите, пожалуйста, а как дождаться появления, полной загрузки рабочего стола (признаки полной загрузки рабочего стола для меня - это появление на рабочем столе значков, отображение панели задач, отображение часов в панели задач и т.д.)

То есть мне что требуется - если загружен рабочи стол - то выполняем комманды
Команда 1
Команда 2
Команда 3
...
Если не загружен рабочий стол - то пауза, ждем, когда будет загружен рабочий стол, тогда и будем выполнять комманды


Время: 09:54.

Время: 09:54.
© OSzone.net 2001-