Jump to content

[Solved] Open and close child GUI's while main function is executing


Papak
 Share

Recommended Posts

Hello.

I have a small issue with child GUI's I created. Basically what I want to do is to be able to open and close child GUI's  while my main script is running. I am able to open them, but I cannot close them. Here's the scenario:

1. When the autoit script is not running and its idling at the GUIGetMsg() loop, both Log and Help buttons are respondable and will open corresponding child GUI's. I can also close those child GUI's by pressing the red X in the corner.

2. When the autoit script is running and its executing StartScript() function (after pressing the start button), both Log and Help buttons are respondable and will open corresponding child GUI's, but I cannot close those child GUI's by pressing the red X in the corner. I first have to stop the script from running and then the child GUI's will close.

So what seems to be the problem is that GUI messages get queued, but cannot be processed until the script stops executing StartScript() function and goes back to the main GuiGetMsg() loop. That kinda makes sense.

I wasn't able to open them either, until I hooked a _WM_COMMAND. Using _WM_COMMAND kinda worked for opening those GUI's, so I'm assuming I need to move $GUI_EVENT_CLOSE to the _WM_COMMAND function. I tried it, but it didn't work for some reason. Maybe I need to catch WM_CLOSE of the corresponding child GUI's do this? Or maybe I'm approaching this problem all wrong? Is there a simpler way to do this?

 

Here's a runnable example code which shows my problem.
 

#include <GUIConstants.au3>
Global Const $GUI_WIDTH = 260
Global Const $GUI_HEIGHT = 60
Global $bInterruptFlag = 0
CreateGUI()

Func CreateGUI()
    Global $hMainGUI = GUICreate("Main GUI", $GUI_WIDTH, $GUI_HEIGHT)
    Global $idHelpButton = GUICtrlCreateLabel("Help", 50, 20, 41, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    Global $idStartButton = GUICtrlCreateLabel("Start", 100, 20, 70, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    Global $idLogButton = GUICtrlCreateLabel("Log", 150, 20, 70, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))

    Global $hLogGUI = GUICreate("Log", 265, 300, -1, -1, BitOR($WS_POPUP, $WS_CAPTION, $WS_SYSMENU), -1, $hMainGUI)
    GUISetState(@SW_HIDE, $hLogGUI)

    Global $idEditLog = GUICtrlCreateEdit("", 17, 66, 231, 217, $ES_AUTOVSCROLL + $WS_VSCROLL + $ES_READONLY)
    GUICtrlSendMsg($idEditLog, $EM_LIMITTEXT, -1, 0)

    Global $hHelpGUI = GUICreate("Help", 350, 394, -1, -1, BitOR($WS_POPUP, $WS_CAPTION, $WS_SYSMENU), -1, $hMainGUI)
    GUISetState(@SW_HIDE, $hHelpGUI)

    GUISetState(@SW_SHOW, $hMainGUI)
    GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")

    Main()
EndFunc

Func Main()
    While 1
        $hGUIMsg = GUIGetMsg(1)

        Select
            Case $hGUIMsg[0] = $idStartButton
                StartScript()

            Case $hGUIMsg[0] = $GUI_EVENT_CLOSE And $hGUIMsg[1] = $hMainGUI
                GUIDelete()
                Exit

            Case $hGUIMsg[0] = $GUI_EVENT_CLOSE And $hGUIMsg[1] = $hHelpGUI
                GUISetState(@SW_HIDE, $hHelpGUI)

            Case $hGUIMsg[0] = $GUI_EVENT_CLOSE And $hGUIMsg[1] = $hLogGUI
                GUISetState(@SW_HIDE, $hLogGUI)
        EndSelect
    WEnd
EndFunc   ;==>Main

Func StartScript()
    $bInterruptFlag = 0
    Local $i
    While 1
        $i = $i+1
        GUICtrlSetData($idEditLog, $i + @CRLF, 1)
        If _Sleep(300) Then
            ExitLoop
        EndIf
    WEnd
EndFunc   ;==>StartScript

Func _Sleep($iDelay)
    Local $iBegin = TimerInit()
    Do
        Sleep(10)
        If $bInterruptFlag Then
            Return True
        EndIf
    Until TimerDiff($iBegin) > $iDelay
    Return False
EndFunc   ;==>_Interrupt_Sleep

Func _WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    If BitAND($wParam, 0x0000FFFF) = $idStartButton Then $bInterruptFlag = 1

    If BitAND($wParam, 0x0000FFFF) = $idLogButton Then
        GUISetState(@SW_SHOW, $hLogGUI)
    EndIf

    If BitAND($wParam, 0x0000FFFF) = $idHelpButton Then
        GUISetState(@SW_SHOW, $hHelpGUI)
    EndIf
EndFunc   ;==>_WM_COMMAND

 

Edited by Papak
Link to comment
Share on other sites

So I can definitely solve this problem by adding a close button in the child GUI's and then simply catching their messages in the _WM_COMMAND like this:

If BitAND($wParam, 0x0000FFFF) = $idCloseHelpButton Then
    GUISetState(@SW_Hide, $hHelpGUI)
EndIf

That isn't really my preferred solution. First, it clutters the interface with a new button. Second, its a bit redundant, since the window already has an X button dedicated to close the GUI.

 

Here's a runnable example code which solves my problem with an addition of extra button.

#include <GUIConstants.au3>
Global Const $GUI_WIDTH = 260
Global Const $GUI_HEIGHT = 60
Global $bInterruptFlag = 0
CreateGUI()

Func CreateGUI()
    Global $hMainGUI = GUICreate("Main GUI", $GUI_WIDTH, $GUI_HEIGHT)
    Global $idHelpButton = GUICtrlCreateLabel("Help", 50, 20, 41, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    Global $idStartButton = GUICtrlCreateLabel("Start", 100, 20, 70, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    Global $idLogButton = GUICtrlCreateLabel("Log", 150, 20, 70, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))

    Global $hLogGUI = GUICreate("Log", 265, 300, -1, -1, BitOR($WS_POPUP, $WS_CAPTION, $WS_SYSMENU), -1, $hMainGUI)
    GUISetState(@SW_HIDE, $hLogGUI)
    Global $idCloseLogButton = GUICtrlCreateLabel("Close", 150, 20, 70, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))

    Global $idEditLog = GUICtrlCreateEdit("", 17, 66, 231, 217, $ES_AUTOVSCROLL + $WS_VSCROLL + $ES_READONLY)
    GUICtrlSendMsg($idEditLog, $EM_LIMITTEXT, -1, 0)

    Global $hHelpGUI = GUICreate("Help", 350, 394, -1, -1, BitOR($WS_POPUP, $WS_CAPTION, $WS_SYSMENU), -1, $hMainGUI)
    GUISetState(@SW_HIDE, $hHelpGUI)
    Global $idCloseHelpButton = GUICtrlCreateLabel("Close", 150, 20, 70, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))

    GUISetState(@SW_SHOW, $hMainGUI)
    GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")

    Main()
EndFunc

Func Main()
    While 1
        $hGUIMsg = GUIGetMsg(1)

        Select
            Case $hGUIMsg[0] = $idStartButton
                StartScript()

            Case $hGUIMsg[0] = $GUI_EVENT_CLOSE And $hGUIMsg[1] = $hMainGUI
                GUIDelete()
                Exit

            Case $hGUIMsg[0] = $GUI_EVENT_CLOSE And $hGUIMsg[1] = $hHelpGUI
                GUISetState(@SW_HIDE, $hHelpGUI)

            Case $hGUIMsg[0] = $GUI_EVENT_CLOSE And $hGUIMsg[1] = $hLogGUI
                GUISetState(@SW_HIDE, $hLogGUI)
        EndSelect
    WEnd
EndFunc   ;==>Main

Func StartScript()
    $bInterruptFlag = 0
    Local $i
    While 1
        $i = $i+1
        GUICtrlSetData($idEditLog, $i + @CRLF, 1)
        If _Sleep(300) Then
            ExitLoop
        EndIf
    WEnd
EndFunc   ;==>StartScript

Func _Sleep($iDelay)
    Local $iBegin = TimerInit()
    Do
        Sleep(10)
        If $bInterruptFlag Then
            Return True
        EndIf
    Until TimerDiff($iBegin) > $iDelay
    Return False
EndFunc   ;==>_Interrupt_Sleep

Func _WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    If BitAND($wParam, 0x0000FFFF) = $idStartButton Then $bInterruptFlag = 1

    If BitAND($wParam, 0x0000FFFF) = $idLogButton Then
        GUISetState(@SW_SHOW, $hLogGUI)
    EndIf

    If BitAND($wParam, 0x0000FFFF) = $idCloseHelpButton Then
        GUISetState(@SW_Hide, $hHelpGUI)
    EndIf

    If BitAND($wParam, 0x0000FFFF) = $idCloseLogButton Then
        GUISetState(@SW_Hide, $hLogGUI)
    EndIf

    If BitAND($wParam, 0x0000FFFF) = $idHelpButton Then
        GUISetState(@SW_SHOW, $hHelpGUI)
    EndIf
EndFunc   ;==>_WM_COMMAND

 

Edited by Papak
Link to comment
Share on other sites

I found the solution, I was on the right track and with a little bit of Googling, I found out I need to register a new On_WM_SYSCOMMAND message via GUIRegisterMsg().

GUIRegisterMsg($WM_SYSCOMMAND, "On_WM_SYSCOMMAND")

Func On_WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
    Local Const $SC_MOVE = 0xF010
    Local Const $SC_SIZE = 0xF000
    Local Const $SC_CLOSE = 0xF060

    If BitAND($wParam, 0xFFF0) = $SC_CLOSE And $hWnd = $hMainGUI Then
        Close()
    EndIf

    If BitAND($wParam, 0xFFF0) = $SC_CLOSE And $hWnd = $hHelpGUI Then
        GUISetState(@SW_HIDE, $hHelpGUI)
    EndIf

    If BitAND($wParam, 0xFFF0) = $SC_CLOSE And $hWnd = $hLogGUI Then
        GUISetState(@SW_HIDE, $hLogGUI)
    EndIf

    Return $GUI_RUNDEFMSG
EndFunc   ;==>On_WM_SYSCOMMAND

So the complete solution looks like this

#include <GUIConstants.au3>
Global Const $GUI_WIDTH = 260
Global Const $GUI_HEIGHT = 60
Global $bInterruptFlag = 0
CreateGUI()

Func CreateGUI()
    Global $hMainGUI = GUICreate("Main GUI", $GUI_WIDTH, $GUI_HEIGHT)
    Global $idHelpButton = GUICtrlCreateLabel("Help", 50, 20, 41, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    Global $idStartButton = GUICtrlCreateLabel("Start", 100, 20, 70, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    Global $idLogButton = GUICtrlCreateLabel("Log", 150, 20, 70, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))

    Global $hLogGUI = GUICreate("Log", 265, 300, -1, -1, BitOR($WS_POPUP, $WS_CAPTION, $WS_SYSMENU), -1, $hMainGUI)
    GUISetState(@SW_HIDE, $hLogGUI)
    Global $idCloseLogButton = GUICtrlCreateLabel("Close", 150, 20, 70, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))

    Global $idEditLog = GUICtrlCreateEdit("", 17, 66, 231, 217, $ES_AUTOVSCROLL + $WS_VSCROLL + $ES_READONLY)
    GUICtrlSendMsg($idEditLog, $EM_LIMITTEXT, -1, 0)

    Global $hHelpGUI = GUICreate("Help", 350, 394, -1, -1, BitOR($WS_POPUP, $WS_CAPTION, $WS_SYSMENU), -1, $hMainGUI)
    GUISetState(@SW_HIDE, $hHelpGUI)
    Global $idCloseHelpButton = GUICtrlCreateLabel("Close", 150, 20, 70, 23, BitOR($SS_CENTER, $SS_CENTERIMAGE))

    GUISetState(@SW_SHOW, $hMainGUI)
    GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")
    GUIRegisterMsg($WM_SYSCOMMAND, "On_WM_SYSCOMMAND")

    Main()
EndFunc
Func Main()
    While 1
        $hGUIMsg = GUIGetMsg(1)

        Select
            Case $hGUIMsg[0] = $idStartButton
                StartScript()
        EndSelect
    WEnd
EndFunc   ;==>Main

Func StartScript()
    $bInterruptFlag = 0
    Local $i
    While 1
        $i = $i+1
        GUICtrlSetData($idEditLog, $i + @CRLF, 1)
        If _Sleep(300) Then
            ExitLoop
        EndIf
    WEnd
EndFunc   ;==>StartScript

Func _Sleep($iDelay)
    Local $iBegin = TimerInit()
    Do
        Sleep(10)
        If $bInterruptFlag Then
            Return True
        EndIf
    Until TimerDiff($iBegin) > $iDelay
    Return False
EndFunc   ;==>_Interrupt_Sleep

Func _WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    If BitAND($wParam, 0x0000FFFF) = $idStartButton Then $bInterruptFlag = 1

    If BitAND($wParam, 0x0000FFFF) = $idLogButton Then
        GUISetState(@SW_SHOW, $hLogGUI)
    EndIf

    If BitAND($wParam, 0x0000FFFF) = $idCloseHelpButton Then
        GUISetState(@SW_Hide, $hHelpGUI)
    EndIf

    If BitAND($wParam, 0x0000FFFF) = $idCloseLogButton Then
        GUISetState(@SW_Hide, $hLogGUI)
    EndIf

    If BitAND($wParam, 0x0000FFFF) = $idHelpButton Then
        GUISetState(@SW_SHOW, $hHelpGUI)
    EndIf
EndFunc   ;==>_WM_COMMAND
Func On_WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
    Local Const $SC_MOVE = 0xF010
    Local Const $SC_SIZE = 0xF000
    Local Const $SC_CLOSE = 0xF060

    If BitAND($wParam, 0xFFF0) = $SC_CLOSE And $hWnd = $hMainGUI Then
        Exit
    EndIf

    If BitAND($wParam, 0xFFF0) = $SC_CLOSE And $hWnd = $hHelpGUI Then
        GUISetState(@SW_HIDE, $hHelpGUI)
    EndIf

    If BitAND($wParam, 0xFFF0) = $SC_CLOSE And $hWnd = $hLogGUI Then
        GUISetState(@SW_HIDE, $hLogGUI)
    EndIf

    Return $GUI_RUNDEFMSG
EndFunc   ;==>On_WM_SYSCOMMAND

 

 

Thank you. Problem solved.

 

 

Edited by Papak
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...