ExpertNoob Posted April 5, 2009 Share Posted April 5, 2009 (edited) Hello, I am making a simple GUI for a command-line executable (my 2nd AutoIt script!). Once options collected and process started (Run()), clicking the close button of the GUI doesn't have immediate effect! It waits for the spawned process to finish before exiting! Something I'm missing? Here is my event handler: Func Form1Close() If $pid<>0 Then ProcessClose($pid) Exit EndFunc Edited April 5, 2009 by ExpertNoob Link to comment Share on other sites More sharing options...
GEOSoft Posted April 5, 2009 Share Posted April 5, 2009 If you used RunWait() to start $pid that is what it will do, Wait. Otherwise we will have to see enough code to find where you went wrong. George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!" Link to comment Share on other sites More sharing options...
ExpertNoob Posted April 5, 2009 Author Share Posted April 5, 2009 (edited) If you used RunWait() to start $pid that is what it will do, Wait. I chose Run() on purpose to be able to offer Pause/Kill buttons.. Here is my master piece: expandcollapse popup#include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <ProgressConstants.au3> #include <StaticConstants.au3> #include <TabConstants.au3> #include <WindowsConstants.au3> #include <Constants.au3> #Include <WinAPI.au3> #Include <SendMessage.au3> Opt("GUIOnEventMode", 1) Global $pathExe, $options, $pid = 0 #Region ### START Koda GUI section ### Form=myGui 0.kxf $Form1 = GUICreate("myGui 0.1", 562, 268, 455, 309) GUISetOnEvent($GUI_EVENT_CLOSE, "Form1Close") GUISetOnEvent($GUI_EVENT_MINIMIZE, "Form1Minimize") GUISetOnEvent($GUI_EVENT_MAXIMIZE, "Form1Maximize") GUISetOnEvent($GUI_EVENT_RESTORE, "Form1Restore") $Label1 = GUICtrlCreateLabel("Exe path:", 8, 8, 74, 17) ;~ GUICtrlSetOnEvent(-1, "Label1Click") $exePath = GUICtrlCreateInput("C:\MySofts\Dev\Cygwin\bin\sleep.exe", 8, 24, 505, 21) GUICtrlSetOnEvent(-1, "exePathChange") $BtBrowse = GUICtrlCreateButton("...", 520, 24, 33, 21, 0) GUICtrlSetOnEvent(-1, "BtBrowseClick") $Progress1 = GUICtrlCreateProgress(8, 248, 545, 17) $Tab1 = GUICtrlCreateTab(8, 59, 545, 137) GUICtrlSetResizing(-1, $GUI_DOCKWIDTH+$GUI_DOCKHEIGHT) $TabSheetCommand = GUICtrlCreateTabItem("Command") $EditCommand = GUICtrlCreateEdit("", 13, 87, 534, 102, BitOR($ES_AUTOVSCROLL, $WS_VSCROLL) ) GUICtrlSetData(-1, "Type options here") GUICtrlSetOnEvent(-1, "EditCommandChange") GUICtrlSetTip(-1, "command here") $TabSheetOutput = GUICtrlCreateTabItem("Output") GUICtrlSetState(-1,$GUI_SHOW) $EditOutput = GUICtrlCreateEdit("", 13, 87, 534, 102, BitOR($ES_AUTOVSCROLL,$ES_MULTILINE,$ES_WANTRETURN,$WS_VSCROLL,$ES_READONLY)) GUICtrlSetData(-1, "") GUICtrlSetOnEvent(-1, "EditOutputChange") $TabSheetOptions = GUICtrlCreateTabItem("Options") GUICtrlCreateTabItem("") GUICtrlSetOnEvent(-1, "Tab1Change") GUICtrlSetState($TabSheetCommand, $GUI_SHOW); default displayed tab, could be GuiTab.au3//_GUICtrlTab_ClickTab $BtStart = GUICtrlCreateButton("Start", 294, 201, 243, 33, 0) GUICtrlSetOnEvent(-1, "BtStartClick") $BtKill = GUICtrlCreateButton("Kill", 88, 201, 65, 33, 0) GUICtrlSetState(-1, $GUI_DISABLE) $BtPause = GUICtrlCreateButton("Pause", 20, 201, 65, 33, 0) GUICtrlSetState(-1, $GUI_DISABLE) $Group1 = GUICtrlCreateGroup("", 0, 48, 561, 193) GUICtrlCreateGroup("", -99, -99, 1, 1) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 Sleep(100) WEnd Func BtBrowseClick() EndFunc Func BtStartClick() $pathExe = GUICtrlRead($exePath) $options = GUICtrlRead($EditCommand) If Not checkInput() Then return $pid = Run ( $pathExe & " " & $options , @SystemDir , @SW_HIDE, $STDERR_MERGED ) If @error Then MsgBox( 48, "Error!", "Failed to start process with:" & @CRLF & @CRLF & $pathExe & @CRLF & @CRLF & _ _WinAPI_GetLastErrorMessage(), 0, $Form1) return EndIf GUICtrlSetState($TabSheetOutput, $GUI_SHOW) GUICtrlSetState( $BtPause, $GUI_ENABLE) GUICtrlSetState( $BtKill, $GUI_ENABLE) Local $begin = TimerInit() Local $line, $dif, $i = 1 While 1 Sleep(50); don't send CPU to 100%! $line = StdoutRead($pid) If @error Then ExitLoop If $line <> "" Then GUICtrlSetData( $EditOutput, $line & @CRLF, " ") $dif = TimerDiff($begin) If $dif >= ($i*100) Then GUICtrlSetData( $EditOutput, $dif & @CRLF, " ") GUICtrlSetData( $Progress1, 10*$i/20 ) $i += 1 EndIf Wend GUICtrlSetState( $BtPause, $GUI_DISABLE) GUICtrlSetState( $BtKill, $GUI_DISABLE) EndFunc Func checkInput() If $pathExe == 0 Then MsgBox( 48, "Error!", "I cannot read path to executable!") return False EndIf If $pathExe == "" Then MsgBox( 48, "Error!", "No path to executable provided!") GUICtrlSetState($exePath, $GUI_FOCUS) return False EndIf If $options == 0 Then GUICtrlSetState($TabSheetCommand, $GUI_SHOW); could be GuiTab.au3//_GUICtrlTab_ClickTab MsgBox( 48, "Error!", "I cannot read command options!") return False EndIf If $options == "" Then GUICtrlSetState($TabSheetCommand, $GUI_SHOW); could be GuiTab.au3//_GUICtrlTab_ClickTab MsgBox( 48, "Error!", "No command options! Please type in options") GUICtrlSetState($EditCommand, $GUI_FOCUS) return False EndIf return True EndFunc Func BtKillClick() If $pid<>0 Then ProcessClose($pid) EndFunc Func BtPauseClick() EndFunc Func EditCommandChange() EndFunc Func EditOutputChange() EndFunc Func exePathChange() EndFunc Func Form1Close() If $pid<>0 Then ProcessClose($pid) Exit EndFunc Func Form1Maximize() EndFunc Func Form1Minimize() EndFunc Func Form1Restore() EndFunc Func Tab1Change() EndFunc Most event handlers are empty for now, I'm playing with sleep.exe to perform tests.. When I start "sleep.exe 20", clicking the close button (or the kill button) doesn't work. It goes on "sleeping" till the end of the 20 seconds, and then it exits! Thanks. Edited April 5, 2009 by ExpertNoob Link to comment Share on other sites More sharing options...
Authenticity Posted April 5, 2009 Share Posted April 5, 2009 (edited) Problem is that once entered into the loop there is nothing that can stop it in your code. You need Adlib or _Timer_SetTimer or HotKeySet, etc.. to check the button state which means the function needs the get called more frequently than you may guess, maybe like ~100 ms and using _GUICtrlButton_GetState($hButton) to see if the button is clicked. I think the clicked value is 620 and I also may be wrong. ;] Edited April 5, 2009 by Authenticity Link to comment Share on other sites More sharing options...
ExpertNoob Posted April 5, 2009 Author Share Posted April 5, 2009 (edited) @Authenticity Thanks. Since I registered an event handler with the close button: GUISetOnEvent($GUI_EVENT_CLOSE, "Form1Close") Isn't Form1Close() called as soon as I click the close button? Even if BtStartClick() is busy with its spawned process.. That's why I avoided RunWait(), so that event handlers keep receiving messages while spawned process is running.. If I understand you, it's pointless to define event handlers: each time I enter an event handler, I have to keep checking for state of all other controls inside the current one! That can't be Edited April 5, 2009 by ExpertNoob Link to comment Share on other sites More sharing options...
Authenticity Posted April 5, 2009 Share Posted April 5, 2009 (edited) OK, I see I'm writing enough crappy details to myself ;]. So I'll just say this:There is a message queue for each thread that is managed as a linked-list (First In First Out). If the thread is busy handling an event then it's in blocking mode and can't receive and handle any other events until it's done processing the current event. Now timer event, hot-key event, and because of it, Adlib events are not PostMessage events like most of the control notification. They interrupt the thread current execution and control is passes to the interrupt routine until it's done processing it's code and control is return to the thread. Crappy explanation right?You can test it your self. Make 2 programs. First program sends a user message to the second process (SendMessage!), now the second process start to loop for 10 seconds. Try to interact with the the first program that sent the message and see what happen.So because you're adopting GuiOnEventMode you'll need to take care not to block the entire message queue handling a single event for 20 seconds. If you need example about AdlibEnable with _GuiCtrlButton_GetState() I'd like to help.Hope I didn't write too much crap at once.Edit:Opt('GuiOnEventMode', 1) Dim $hGUI = GUICreate('Test', 100, 115) Dim $Button1 = GUICtrlCreateButton('Test1', 20, 40, 60, 23) Dim $Button2 = GUICtrlCreateButton('Test2', 20, 80, 60, 23) GUICtrlSetOnEvent($Button1, 'TestFunc1') GUICtrlSetOnEvent($Button2, 'TestFunc2') GUISetOnEvent(-3, '_EXIT') GUISetState() While 1 Sleep(20) WEnd Func _EXIT() GUIDelete() Exit EndFunc Func TestFunc1() ToolTip('Try to close the window' & @LF & 'or better click "Test2"', @DesktopWidth-140, 0) Sleep(10000) EndFunc Func TestFunc2() ConsoleWrite('-Got a message :-)' & @LF) EndFunc Edited April 5, 2009 by Authenticity Link to comment Share on other sites More sharing options...
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