Jump to content



Photo

Help! Cannot exit my main form during a processing loop, using GUIOnEventMode.


  • Please log in to reply
5 replies to this topic

#1 tfabris

tfabris

    Seeker

  • Active Members
  • 18 posts

Posted 26 May 2012 - 09:37 PM

Can anyone tell me what I'm doing wrong here?

Run this program and notice that, you can close the application just fine if you close it before pressing the "Being Processing Now" button.
Then run it again, and notice that, you cannot close the application after pressing the "Begin Processing Now" button.

Is there a way to fix this?

AutoIt         
; Example of problem I'm having with the GUI not closing. ; How do I fix this? #include <GuiEdit.au3> #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> Opt("GUIOnEventMode", 1) $MainForm = GUICreate("Test Application", 600, 400, 200, 200, BitOR($WS_MAXIMIZEBOX,$WS_MINIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_SYSMENU,$WS_CAPTION,$WS_OVERLAPPEDWINDOW,$WS_TILEDWINDOW,$WS_POPUP,$WS_POPUPWINDOW,$WS_GROUP,$WS_TABSTOP,$WS_BORDER,$WS_CLIPSIBLINGS)) GUISetOnEvent($GUI_EVENT_CLOSE, "MainFormClose") $LogOutputTextBox = GUICtrlCreateEdit("", 8, 8, 580, 280, BitOR($ES_READONLY,$ES_WANTRETURN,$WS_HSCROLL,$WS_VSCROLL)) $GoButton = GUICtrlCreateButton("Begin Processing Now !", 8, 300, 237, 33, $WS_GROUP) GUICtrlSetOnEvent($GoButton, "ProcessingLoop") GUISetState(@SW_SHOW) While 1    ; Loop where the main application waits for user input.    ; This works... If it reaches this and the user presses the main    ; form close button, then the application closes just fine.    Sleep (1000) WEnd Func MainFormClose ()    ; This works fine, unless I'm in the processing loop.    ; Why does this not work when I'm in the processing loop?    MsgBox (0, "Closing", "You pressed the close button! Yay! Now exiting.")    Exit EndFunc Func ProcessingLoop ()    ; This loop simulates the main application processing loop.    ; This is the part that I cannot exit. I'm putting sleeps in    ; here like crazy. Why doesn't the Close Button event fire    ; when I'm in this loop?    For $x = 1 to 30    ; If this were a real application, I would be doing something important here,    ; like calculating the Question to the Ultimate Answer. But just for demo    ; purposes, I'm going to just output some text.    OutputText ("I am doing something. I have done something " & $x & " times now.")    OutputText ("Boy I sure wish I could exit this application now.")    OutputText ("Unfortunately, I must be task-killed now. WHY?!")       Sleep (1000)    Next EndFunc Func OutputText ($TextLine)    ; Subroutine that makes it easy to output text to the edit control, for demonstration purposes.    GuiCtrlSetData( $LogOutputTextBox, GuiCtrlRead ($LogOutputTextBox) & $TextLine & @CRLF)    _GUICtrlEdit_LineScroll($LogOutputTextBox, 0, _GUICtrlEdit_GetLineCount($LogOutputTextBox)) EndFunc






#2 water

water

    ?

  • MVPs
  • 10,643 posts

Posted 26 May 2012 - 09:45 PM

The AutoIt help file tells you:
"OnEvent Mode
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 halts 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."

Therefore: As long as function ProcessingLoop is running the script doesn't check for any other GUI events.

Edited by water, 26 May 2012 - 09:45 PM.

UDFs:

Active Directory (2012-10-12 - Version 1.3.0.0 released) - Download - General Help & Support - Example Scripts - Wiki

OutlookEX (2012-10-07 - Version 0.9.0.0 released) - Download - General Help & Support - Example Scripts - Wiki

ExcelChart (2013-01-21 - Version 0.3.1.1 released) - Download - General Help & Support - Example Scripts

WordEX (2012-12-29 - Version 1.3 released) - Download

ExcelEX (2013-05-11 - Alpha 4 released) - Download


#3 AoRaToS

AoRaToS

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 324 posts

Posted 26 May 2012 - 09:57 PM

have a look at Hotkeys

s!mpL3 LAN MessengerCurrent version 2.9.7.7 [15/02/2013]Download HeresimpL3


#4 tfabris

tfabris

    Seeker

  • Active Members
  • 18 posts

Posted 27 May 2012 - 12:13 AM

Thanks for that explanation, Water! I have crafted a solution based on your explanation, thank you!

I discovered that I could process GUI events in the middle of other functions just fine, so the explanation didn't make sense to me at first. I had to poke at things a bit to figure out exactly what it meant. I think a more accurate description, better than what is says in the Help, would be something like:

"If the GUI fires off one of its event handlers for one of its controls, it won't process any more GUI events until that particular event handler returns."

In other words, the problem isn't just that you can't call out to any functions at all, which is what I initially interpreted the explanation to mean. No, the problem is that you can't do a bunch of code (or sub-call out to a bunch of code) directly from the GUI event handler. If you do, then it won't ever return and the GUI never processes any other events. (I guess the GUI is single threaded or something?)

Anyway, with that knowledge, I was able to come up with a perfect solution that doesn't require rewriting the whole thing in Message-Loop mode. Instead of trying to call my main processing function from the button code, the button code sets a flag. That flag is then read by the main program loop and then fired off from within the main program loop. *THAT* works fine and I can terminate the program easily wherever I want now, even if the processing loop takes hours.

Pseudo code of my solution looks something like this:

Plain Text         
; ------------- ; BAD (ORIGINAL) CODE ; -------------     GUICreate("Test Application")     GUICtrlSetOnEvent($GoButton, "ProcessingLoop")     While 1          Sleep(1000)     Wend     Func ProcessingLoop()           ;Do lotsa stuff     End Func ; ------------- ; GOOD (MY SOLUTION) CODE ; -------------     Global $GoFlag = 0     GUICreate("Test Application")     GUICtrlSetOnEvent($GoButton, "SetGoFlag")     While 1          Sleep(1000)          If $GoFlag == 1 Then                 ProcessingLoop()                 $GoFlag = 0          EndIf     Wend     Func SetGoFlag()            $GoFlag = 1     End Func     Func ProcessingLoop()           ;Do lotsa stuff     End Func


#5 Melba23

Melba23

    Yes, me!

  • Moderators
  • 15,301 posts

Posted 27 May 2012 - 08:16 AM

tfabris,

Take a look at the Interrupting a running function tutorial in the Wiki - shows the various ways you can do it in AutoIt. ;)

M23
StringSize - Automatically size controls to fit text - ExtMsgBox - A user customisable replacement for MsgBox

Toast - Small GUIs which pop out of the Systray - Marquee - Scrolling tickertape GUIs

Scrollbars - Automatically sized scrollbars with a single command - GUIFrame - Subdivide GUIs into many adjustable frames

GUIExtender - Extend and retract multiple sections within a GUI - NoFocusLines - Remove the dotted focus lines from buttons, sliders, radios and checkboxes

ChooseFileFolder - Single and multiple selections from specified path tree structure - - Notify - Small notifications on the edge of the display

RecFileListToArray - An alternative to _FileListToArray with user-defined include/exclude masks, maximum recursion level, sorting and displayed path options

GUIListViewEx - Insert, delete, move, drag and sort ListView items


#6 tfabris

tfabris

    Seeker

  • Active Members
  • 18 posts

Posted 27 May 2012 - 07:51 PM

Take a look at the Interrupting a running function tutorial in the Wiki - shows the various ways you can do it in AutoIt. ;)


Yup, one of the methods shown in that Wiki entry was the one I ended up coming up with on my own. Thanks!




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users