GUI 相关 - 事件模式

In the OnEvent mode instead of constantly polling the GUI to find out if anything has happened you make the GUI temporarily pause your script and call a pre-defined function to handle the event. For example, if the user clicks Button1 the GUI pauses your main script and calls a previously defined user function that deals with Button1. When the function call is completed the main script is resumed. This mode is similar to the Visual Basic forms method.

While the GUI is executing, your main script could be doing any normal scripting work, but for ease of examples we will just make the main script "idle" in an infinite While loop.

The default mode is the MessageLoop mode so before using the OnEvent mode we must use Opt("GUIOnEventMode", 1).

Basic OnEvent Format

The general layout of OnEvent code is:

While 1
    Sleep(100) ; Sleep to reduce CPU usage
WEnd

Func Event1()
    ; Code to handle event goes here
EndFunc   ;==>Event1

Func Event2()
    ; Code to handle event goes here
EndFunc   ;==>Event2

GUI Events

In the OnEvent mode your GUI will generate the following "events":

Both types of event will call a user defined function if one was set for the GUI (GUISetOnEvent) or for a control (GUICtrlSetOnEvent). If no functions are defined for an event then it is simply ignored. When inside this called function various macros will be set to values to help process the event.

Macro Details
@GUI_CTRLID The control ID of the control sending the message OR the system event ID
@GUI_WINHANDLE The handle of the GUI that sent the message
@GUI_CTRLHANDLE The handle of the Control that sent the message (if applicable)

Note: It is perfectly legal to use the same function for multiple events, all that you need to do in these cases is to take action based on the @GUI_CTRLID macro. For example, you could register all system events to the same function.

 

Control Event

When a control is clicked or changes a control event is sent. The event is sent to the function defined with GUICtrlSetOnEvent. Inside the user defined function @GUI_CTRLID is set to the controlID that was returned when the control was created with GUICtrlCreate....

 

System Event

System events - such as the GUI closing - are sent in a similar way to Control event, but the event type is defined by @GUI_CTRLID. The event is sent to the function defined with GUISetOnEvent. The possible system event values are shown here:

$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

Example GUI

In the main GUI Reference page we started a simple Hello World example that looked like this:

#include <GUIConstantsEx.au3>

GUICreate("Hello World", 200, 100)
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
GUICtrlCreateButton("OK", 70, 50, 60)
GUISetState(@SW_SHOW)
Sleep(2000)

 

Now we will finish the code using OnEvents and some of the event messages described above.

#include <GUIConstantsEx.au3>

Opt("GUIOnEventMode", 1) ; Change to OnEvent mode

Local $hMainGUI = GUICreate("Hello World", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton")
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
Local $iOKButton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($iOKButton, "OKButton")
GUISetState(@SW_SHOW, $hMainGUI)

While 1
    Sleep(100) ; Sleep to reduce CPU usage
WEnd

Func OKButton()
    ; Note: At this point @GUI_CtrlId would equal $iOKButton,
    ; and @GUI_WinHandle would equal $hMainGUI
    MsgBox(0, "GUI Event", "You selected OK!")
EndFunc   ;==>OKButton

Func CLOSEButton()
    ; Note: At this point @GUI_CtrlId would equal $GUI_EVENT_CLOSE,
    ; and @GUI_WinHandle would equal $hMainGUI
    MsgBox(0, "GUI Event", "You selected CLOSE! Exiting...")
    Exit
EndFunc   ;==>CLOSEButton

It's that simple. Obviously the more windows and controls you create the more complicated it gets but the above shows you the basics.

Advanced Operations and Multiple Windows

Control IDs are unique, even when you have multiple windows but how do we handle multiple windows?

Here is an example similar to the one above but with another "dummy" window.

#include <GUIConstantsEx.au3>

Opt("GUIOnEventMode", 1) ; Change to OnEvent mode

Global $hMainGUI = GUICreate("Hello World", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton")
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
Local $iOKButton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($iOKButton, "OKButton")

Global $hDummyGUI = GUICreate("Dummy GUI for testing", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton")

GUISwitch($hMainGUI)
GUISetState(@SW_SHOW)

While 1
    Sleep(100) ; Sleep to reduce CPU usage
WEnd

Func OKButton()
    ; Note: At this point @GUI_CtrlId would equal $iOKButton
    MsgBox(0, "GUI Event", "You selected OK!")
EndFunc   ;==>OKButton

Func CLOSEButton()
    ; Note: at this point @GUI_CtrlId would equal $GUI_EVENT_CLOSE,
    ; @GUI_WinHandle will be either $hMainGUI or $hDummyGUI
    If @GUI_WinHandle = $hMainGUI Then
        MsgBox(0, "GUI Event", "You selected CLOSE in the main window! Exiting...")
        Exit
    EndIf
EndFunc   ;==>CLOSEButton

 

The first major change is the GUISwitch function call - when a new window is created it becomes the "default" window for future GUI operations (including control creation). In our case we want to work with the main "Hello World" window, not the test window, so we "switch". Some GUI functions allow you to use the window handle in the function call itself - these functions will do the switch automatically. In our example we could have done this with:

GUISetState(@SW_SHOW, $hMainGUI)

 

Also notice that we used the same OnEvent function to handle the "close" button for both windows and then used @GUI_WINHANDLE to determine which window sent the message - then we only closed the GUI when the close button was clicked and the message came from the main window. You can just as easily use separate functions for each window if you wish.