В режиме OnEvent (по событию) вместо постоянного опроса GUI для обнаружения произошедшего события, выполняется временная приостановка скрипта и вызов назначенных функций связанных с определёнными элементами управления. Например, если пользователь нажимает кнопку Button1, GUI приостанавливает основной скрипт и вызывает ранее определенную пользователем функцию связанную с Button1. После выполнения функции приостановленный основной скрипт возобновляет работу. Этот режим аналогичен методу формы в Visual Basic.
Пока выполняется GUI, ваш основной скрипт может выполнять любую обычную скриптовую работу, но для простоты примера мы просто сделаем основной скрипт с "бездействующим" бесконечным циклом (While).
По умолчанию используется режим MessageLoop (цикл опроса GUI), поэтому перед использованием режима OnEvent (по событию) мы должны использовать Opt("GUIOnEventMode", 1).
Основной формат OnEvent выглядит так:
While 1
Sleep(1000) ; Обычное ожидание в цикле
WEnd
Func Event1()
; Код выполняющийся при событии
EndFunc
Func Event2()
; Код выполняющийся при событии
EndFunc
В режиме OnEvent ваш GUI выдаёт следующие события:
Оба типа события вызывают пользовательскую функцию, если она была установлена для системных событий GUI с помощью GUISetOnEvent или для элемента управления с помощью GUICtrlSetOnEvent. Если для события не назначена функции, то оно просто игнорируется. При этом внутри вызываемой функции различным макросам присваиваются значения, чтобы помочь выполнению события.
Макрос | Подробнее |
---|---|
@GUI_CtrlId | Идентификатор элемента управления выславший сообщение ИЛИ системный идентификатор события (ID) |
@GUI_WinHandle | Дескриптор GUI выславший сообщение |
@GUI_CtrlHandle | Дескриптор элемента управления выславший сообщение (если необходимо) |
Примечание: Это совершенно нормально использовать одну и ту же функцию для разных событий. Всё, что необходимо сделать в таких случаях - внутри функции выбрать действие в зависимости от макроса @GUI_CtrlId. Например, вы можете назначить всем системным событиям одну и ту же функцию.
Событие от элемента управления
При клике на элементах управления или при их изменении, высылается сообщение. Событие высылается функции, назначаемой с помощью GUICtrlSetOnEvent. Внутри пользовательской функции макросу @GUI_CtrlId присваивается идентификатор элемента управления, который возвращается функцией GUICtrlCreate... при его создании.
Системное событие
Системные события - такие, как закрытие GUI - высылаются подобно событиям элементов управления, но тип события определяется макросом @GUI_CtrlId. Событие высылается функции, назначаемой с помощью GUISetOnEvent. Возможные значения системных событий, показаны ниже:
$GUI_EVENT_CLOSE
$GUI_EVENT_MINIMIZE
$GUI_EVENT_RESTORE
$GUI_EVENT_MAXIMIZE
$GUI_EVENT_PRIMARYDOWN
$GUI_EVENT_PRIMARYUP
$GUI_EVENT_SECONDARYDOWN
$GUI_EVENT_SECONDARYUP
$GUI_EVENT_MOUSEMOVE
$GUI_EVENT_RESIZED
$GUI_EVENT_DROPPED
На главной странице Описание GUI мы начали делать простой пример "Привет Мир", который выглядел следующим образом:
#include <GUIConstantsEx.au3>
GUICreate("Привет Мир", 200, 100)
GUICtrlCreateLabel("Привет Мир! Как дела?", 30, 10)
GUICtrlCreateButton("OK", 70, 50, 60)
GUISetState(@SW_SHOW)
Sleep(2000)
Теперь мы завершим код, используя режим OnEvents (по событию) и некоторые сообщения от событий, описанных выше.
#include <GUIConstantsEx.au3>
Opt("GUIOnEventMode", 1) ; Включает режим OnEvent
$mainwindow = GUICreate("Привет мир", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("Привет мир! Как дела?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")
GUISetState(@SW_SHOW)
While 1
Sleep(1000) ; Цикл ожидания
WEnd
Func OKButton()
;Примечание: в этом месте @GUI_CtrlId равен $okbutton,
;и @GUI_WinHandle равен $mainwindow
MsgBox(0, "Событие GUI", "Вы нажали OK!")
EndFunc
Func CLOSEClicked()
;Примечание: в этом месте @GUI_CtrlId равен $GUI_EVENT_CLOSE,
;и @GUI_WinHandle равен $mainwindow
MsgBox(0, "Событие GUI", "Вы нажали CLOSE! Завершаем...")
Exit
EndFunc
Это очень простой пример. Очевидно, что чем больше окон и элементов управления вы используете, тем сложнее он становится, но выше указанное показывает вам основы.
Идентификатор элементов управления (ID) являются уникальным, даже если у вас есть несколько окон, но как работать с несколькими окнами?
Вот пример, аналогичный приведенному выше, но с другим "пустым" окном.
#include <GUIConstantsEx.au3>
Opt("GUIOnEventMode", 1) ; Включает режим OnEvent
$mainwindow = GUICreate("Привет мир", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("Привет мир! Как дела?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")
$dummywindow = GUICreate("Пустое окно для теста ", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUISwitch($mainwindow)
GUISetState(@SW_SHOW)
While 1
Sleep(1000) ; Цикл ожидания
WEnd
Func OKButton()
;Примечание: в этом месте @GUI_CtrlId равен $okbutton,
MsgBox(0, "GUI Event", "Вы нажали OK!")
EndFunc
Func CLOSEClicked()
;Примечание: в этом месте @GUI_CtrlId равен $GUI_EVENT_CLOSE,
;@GUI_WinHandle может быть либо $mainwindow, либо $dummywindow
If @GUI_WinHandle = $mainwindow Then
MsgBox(0, "GUI Event", "Вы нажали CLOSE в основном окне! Завершаем...")
Exit
EndIf
EndFunc
Первым заметным изменением является вызов функции GUISwitch. Когда создается новое окно, оно становится "по умолчанию" для будущих операций с GUI (в том числе создание элементов управления). В нашем случае мы хотим работать с главным окном "Привет Мир", а не в тестовом окне, таким образом мы "переключаем". Некоторые функции GUI позволяют использовать дескриптор окна в своих параметрах - эти функции переключают автоматически. В нашем примере мы можем сделать это с помощью:
GUISetState(@SW_SHOW, $mainwindow)
Также заметьте, что мы использовали ту же функцию OnEvent для обработки кнопки "Закрыть" обоих окон и далее использовали @GUI_WinHandle, чтобы определить, какое окно выслало сообщение - и только потом закрыли GUI, когда была нажата кнопка закрытия и сообщение закрытия пришло из главного окна. Если хотите, вы можете использовать отдельные функции для каждого окна.