GUI 相关 - 消息循环模式

In the MessageLoop mode your script will spend the majority of its time in a tight loop. This loop will simply poll the GUI using the GUIGetMsg function. When an event has occurred the return value of the GUIGetMsg function will show the details (a button is clicked, the GUI has been closed, etc.).

The MessageLoop mode is the default message mode for AutoIt GUIs - the other possible mode is the OnEvent mode.

In the MessageLoop mode you will only receive events while you are actively polling the GUIGetMsg function so you must ensure that you call it many times a second otherwise your GUI will be unresponsive.

 

基本的 消息循环 结构

下面是 消息循环 的基本结构代码:

While 1
  $msg = GUIGetMsg()
  ...
  ...
WEnd

 

像上面这种循环周期非常短的脚本通常会把CPU占用推到高达 100%,幸运的是 GUIGetMsg 函数可在无事件等待时自动闲置CPU.另外千万 不要 因为怕增加CPU压力而自己添加休眠语句(Sleep)到脚本中,这么做只会让GUI响应迟钝.

 

GUI 事件

GUIGetMsg返回的事件消息有以下三种:

  • 无事件
  • 控件事件
  • 系统事件
  •  

    无事件

    没有截获任何事件时 GUIGetMsg 的返回值为 0.这也是 最常发生的事件.

     

    控件事件

    当某个控件被点击或该控件有其它变化时将发送控件事件。这些事件代码都是正数并且关联发送事件消息的 控件ID(也即使用 GUICtrlCreate... 函数创建该控件时的返回值).

     

    系统事件

    系统事件包括GUI(窗口)被关闭等在内,它们的值都是 负数.下面列出了各种系统事件(在 GUIConstantsEx.au3 中有定义):

    $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("确定", 70, 50,60)
    GUISetState(@SW_SHOW)
    Sleep(2000)

     

    现在我们来尝试使用 消息循环 以及上面描述的事件消息来完成全部代码.为了脚本的可读性考虑我们使用条件选择语句.

     

    #include <GUIConstantsEx.au3>

    GUICreate("你好世界", 200, 100)
    GUICtrlCreateLabel("你好世界!你好么?", 30, 10)
    $okbutton = GUICtrlCreateButton("确定", 70, 50, 60)
    GUISetState(@SW_SHOW)

    While 1
      $msg = GUIGetMsg()

      Select
        Case $msg = $okbutton
          MsgBox(0, "GUI 事件", "您按下了[确定]按钮!")

        Case $msg = $GUI_EVENT_CLOSE
          MsgBox(0, "GUI 事件", "您选择了关闭!正在退出...")
          ExitLoop
      EndSelect
    WEnd

    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 GUIGetMsg and Multiple Windows

    Control IDs are unique, even when you have multiple windows, so the above code with work fine with controls and multiple windows.  However, when processing events such as $GUI_EVENT_CLOSE or $GUI_MOUSEMOVE you need to know which GUI window generated the event.  To do this you must call GUIGetMsg like so:

    $msg = GUIGetMsg(1)

     

    When called with the 1 parameter instead of returning an event value an array will be returned, the array contains the event ( in $array[0] ) and extra information such as the window handle ( in $array[1] ).  If two windows were created in the previous example then the correct way to write the code would be:

    #include <GUIConstantsEx.au3>

    $mainwindow = GUICreate("Hello World", 200, 100)
    GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
    $okbutton = GUICtrlCreateButton("OK", 70, 50, 60)

    $dummywindow = GUICreate("Dummy window for testing ", 200, 100)

    GUISwitch($mainwindow)
    GUISetState(@SW_SHOW)

    While 1
      $msg = GUIGetMsg(1)

      Select
        Case $msg[0] = $okbutton
          MsgBox(0, "GUI Event", "You pressed OK!")

        Case $msg[0] = $GUI_EVENT_CLOSE And $msg[1] = $mainwindow
          MsgBox(0, "GUI Event", "You clicked CLOSE on the main window! Exiting...")
          ExitLoop
      EndSelect
    WEnd

     

    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, $mainwindow)

     

    The next change is the way GUIGetMsg is called and how the events are checked - notice the use of $msg[0] and $msg[1] - now we only exit the script if the close event is sent and the event is from our main window.