Papak Posted August 23, 2019 Posted August 23, 2019 (edited) 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. expandcollapse popup#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 August 23, 2019 by Papak
Papak Posted August 23, 2019 Author Posted August 23, 2019 (edited) 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. expandcollapse popup#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 August 23, 2019 by Papak
Papak Posted August 23, 2019 Author Posted August 23, 2019 (edited) 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 expandcollapse popup#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 August 23, 2019 by Papak
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now