Описание GUI - режим OnEvent (по событию)

В режиме OnEvent (по событию) вместо постоянного опроса GUI для обнаружения произошедшего события, выполняется временная приостановка скрипта и вызов назначенных функций связанных с определёнными элементами управления. Например, если пользователь нажимает кнопку Button1, GUI приостанавливает основной скрипт и вызывает ранее определенную пользователем функцию связанную с Button1. После выполнения функции приостановленный основной скрипт возобновляет работу. Этот режим аналогичен методу формы в Visual Basic.

Пока выполняется GUI, ваш основной скрипт может выполнять любую обычную скриптовую работу, но для простоты примера мы просто сделаем основной скрипт с "бездействующим" бесконечным циклом (While).

По умолчанию используется режим MessageLoop (цикл опроса GUI), поэтому перед использованием режима OnEvent (по событию) мы должны использовать Opt("GUIOnEventMode", 1).


Основной формат OnEvent (по событию)

Основной формат OnEvent выглядит так:

While 1
  Sleep(1000)   ; Обычное ожидание в цикле
WEnd
  
Func Event1()
  ; Код выполняющийся при событии
EndFunc

Func
Event2()
  ; Код выполняющийся при событии
EndFunc


События GUI

В режиме 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

    На главной странице Описание 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, когда была нажата кнопка закрытия и сообщение закрытия пришло из главного окна. Если хотите, вы можете использовать отдельные функции для каждого окна.