Что нового

[Элементы GUI] Не работают кнопки на стартовой форме при переключении на неё

TheAnswer

Новичок
Сообщения
9
Репутация
0
Доброго времени суток!
Пишу скрипт для автоматизации длительного процесса. Есть стартовая экранная форма с Label'ами, Input'ами и кнопками "Ок" и "Продолжить". На кнопку "Ок" повесил функцию, при которой считываются введённые с экрана данные и запускается сам процесс. Если на каком-то этапе падает ошибка, то скрипт возвращает на стартовую форму для корректировки введённых данных. После редактирования планируется нажимать кнопку "Продолжить", которая возвратит к этапу, на котором эта ошибка и выпадала.

Проблемы:
1. После того, как процесс запускается по нажатию кнопки "Ок" и возникновении ошибки, обе кнопки на стартовой экранной форме не работают. Пробовал проверить с помощью отладочного вывода в консоль / MsgBox - пытался понять на каком шаге валится, но безрезультатно. В обработчик клавиши "Продолжить" скрипт даже не заходит.
2. При подобной ошибке стартовая форма не закрывается при нажатии на крест в правом верхнем углу экрана. Проблему решает только диспетчер задач через завершение процесса.

Вопросы:
1. Как активировать кнопку "Продолжить"?
2. Как корректно завершать этот процесс / как сделать так, чтобы эта форма не зависала?

Приложу часть кода:
Код:
Opt("GUIOnEventMode", 1);
$hMain = GUICreate("Главное окно", 600, 600)
...
$btOk = GUICtrlCreateButton("ОК", 230, 500, 60, 20)
$btCont = GUICtrlCreateButton("Продолжить", 300, 500, 80, 20)
...
GUICtrlSetOnEvent($btOk, "OkBtAction")
GUICtrlSetOnEvent($btCont, "ContBtAction")
GUISetOnEvent($GUI_EVENT_CLOSE, "CloseBtAction")
...
Func ContBtAction()
   IF $curTitle == $secondTitle THEN
      $f = GUICtrlRead($firstName);
      $m = GUICtrlRead($middleName);
      $l = GUICtrlRead($lastName);
      $a = GUICtrlRead($age);
      WinActivate($curTitle)
   EndIf
EndFunc

Func OkBtAction()
    $f = GUICtrlRead($firstName);
    $m = GUICtrlRead($middleName);
    $l = GUICtrlRead($lastName);
    $a = GUICtrlRead($age);

   start()

   ; Шаг 1: пропускаем
   nextStep($firstTitle, $btNext)

   ; Шаг 2
   secondStep()

   ; Шаг 3: пропускаем
   nextStep($thirdTitle, $btNext)

   ; Шаг 4:
   fourthStep()

   ; Шаг 5: пропускаем
   nextStep($fifthTitle, $btNext)

   ; Шаг 6
   sixthStep()

   Exit;
EndFunc

; одна из функций, в которых может упасть ошибка на панельке "Уведомление"
Func secondStep()
   WinWaitActive($secondTitle)
   $curTitle = $secondTitle
   ...
   WinWaitActive("Уведомление")
   $res = ControlGetText("Уведомление", "", 2);
   if $res == $error Then
	  ControlClick("Уведомление", "OK", 2)
	  MsgBox(4096, "Ошибка!", "Введены некорректные данные")
	  WinActivate($hMain)
          WinWaitActive($secondTitle)
	  secondStep()
   Else
	  ControlClick("Уведомление", "Да", 3) ; подтверждаем корректность
	  ControlClick($secondTitle, "Далее", 26) ; идем на следующий шаг
   EndIf
EndFunc

Func CloseBtAction()
  Exit
EndFunc


Очень нужна помощь.
 

alex33

Скриптер
Сообщения
1,457
Репутация
186
Попробуйте функции WinWaitActive установить timeout (третий параметр)... Например:
Код:
WinWaitActive($secondTitle, "", 5)
 
Автор
T

TheAnswer

Новичок
Сообщения
9
Репутация
0
Не понимаю зачем ставить тайм-аут, если у меня не работают кнопки :smile:
Но я всё равно попробовал - не помогло :D

Я решил попробовать запускать с функцией Sleep($time).
Идея заключалась в её использовании на 10 секунд после ввода некорректных данных. За эти 10 секунд должно произойти:
1. Активация первоначальной формы
2. Правка первоначальных значений на корректные
3. Завершение Sleep
Далее считываю новые значения и продолжаю с формы, на которой упала ошибка. Но новые значения с экрана не читаются, Sleep не заканчивается и не активируется окно, где падала ошибка.

Никто с подобным не сталкивался?
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Очень зря не понимаете. Как только скрипт дойдет до любой функции с .WAIT то встанет на паузу, и ни какие кнопки не будут работать.
 
Автор
T

TheAnswer

Новичок
Сообщения
9
Репутация
0
Так всё верно, я жду пока пользователь не нажмет кнопку "Продолжить". В этой кнопке я намеренно активизирую окно, из которого прилетела ошибка, чтобы продолжить выполнение скрипта с корректными данными.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
А где ждете? Ждать нужно в главном цикле while 1... wend. Если при нажатии на "Продолжить" программа зависла где то в другом месте то не сработает.
Вообще старайтесь писать так, что бы в функциях назначенных на обработку событий было как можно меньше кода. Идеально, когда такие функции просто фиксируют факт нажатия, а в главном цикле - обрабатываешь. И еще, у вас secondStep() рекурсия.
 
Автор
T

TheAnswer

Новичок
Сообщения
9
Репутация
0
В главном цикле у меня стоит Sleep(1000). Судя по всему, это большой косяк. У меня два вопроса:
1. Этот цикл нужно обернуть в функцию?
2. В этот цикл помещать все WinWaitActive()?

Рекурсию сделал из-за того, что функцию нужно перезапустить, чтобы сетить нужные значения и затем успешно выполнить пункт.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Я обычно делал так:
На кнопки вешал один обработчик, в главном цикле решал что делать.
Если нужно возвращаться к этапу на котором была ошибка то я бы делал так.
Например, я должен проконтролировать работу калькулятора, сперва я должен ввести 1, затем 2 итд до 5, если я все правильно сделал, то работа считается выполнена. Если я ввожу 8 (так я симулирую ошибку) то предлагается исправить число и после этого цикл будут продолжен именно с нужного этапа.

Код:
Opt("GUIOnEventMode", 1);

#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

$hMain = GUICreate("Главное окно", 600, 600)

$btOk = GUICtrlCreateButton("Go", 230, 500, 60, 20)

GUICtrlSetOnEvent($btOk, "onClick")
GUISetOnEvent(-3, "onClose")
GUISetState()

Global $target


While 1
	Sleep(250)

	Switch $target
		Case $btOk
			okAction()
	EndSwitch

WEnd

Func okAction()

	$target = Null

	ConsoleWrite('okAction' & @CRLF)

	;;Запускаем долгий процесс.

	Static $running = False
	Static $stage = 1, $finalStage = 6

	If $running Then Return

	$running = True

	guiRunning($running)
	Local $wait = ''
	Do

		Switch $stage
			Case 1
				$wait = 1
			Case 2
				$wait = 2
			Case 3
				$wait = 3
			Case 4
				$wait = 4
			Case 5
				$wait = 5
		EndSwitch

		$h = WinWaitActive('Калькулятор')
		$res = ControlGetText($h, '', '[CLASS:Static; INSTANCE:4]')

		If $res = $wait Then
			MsgBox(0, 'Ok', 'Этап: ' & $stage & ' завершен')
			$stage +=1
			ContinueLoop
		EndIf

		If $res = 8 Then
			MsgBox(0, 'Ошибка', 'Вы должны ввести правильные данные что бы завершить этап')
		EndIf

	Until $stage = $finalStage

	$running = False
	$stage = 1
	guiRunning($running)

	MsgBox(0, 'Ок', 'Все завершено.')

EndFunc

Func proceedAction()
	$target = Null
EndFunc

Func onClick()
	$target = @GUI_CtrlId
EndFunc

Func onClose()
	Exit
EndFunc

Func guiRunning($status = False)
	If $status Then
		GUICtrlSetState($btOk, $GUI_DISABLE)
		GUICtrlSetData($btOk, 'Работаем...')
	Else
		GUICtrlSetState($btOk, $GUI_ENABLE)
		GUICtrlSetData($btOk, 'Go')
	EndIf
EndFunc
 
Верх