Expansion Posted February 27, 2011 Posted February 27, 2011 main() is a waiting for a specified window, and I can't use the interface during this period. How should I develop a GUI application that uses blocking functions? The only thing that I can think of right now are threads, but I have no clue about threads and AutoIt. expandcollapse popup#include <GUIConstantsEx.au3> #include <TreeviewConstants.au3> #include <WindowsConstants.au3> #include <EditConstants.au3> #include <StaticConstants.au3> #Include <GuiButton.au3> #Include <Array.au3> Opt("GUIOnEventMode", 1) ; Change to OnEvent mode Opt("MustDeclareVars", 1) Func main() dim $treeview_hwnd $treeview_hwnd =WinWait("Select Folder","") ...... EndFunc dim $mainwindow dim $start, $stop, $increment, $decrement, $status $mainwindow=GUICreate("My GUI edit", 600, 300) $status = GUICtrlCreateEdit("status" , 0 , 280 , 600, 20, $ES_READONLY) $start = GUICtrlCreateButton ( "Start", 300, 250, 90, 20) GUICtrlSetOnEvent(-1, "STARTClicked") $stop = GUICtrlCreateButton( "Stop", 400, 250, 90, 20) GUICtrlSetOnEvent(-1, 'STOPClicked') $increment = GUICtrlCreateButton("+", 100, 250, 90, 20) GUICtrlSetOnEvent(-1, "increment") $decrement = GUICtrlCreateButton( "-", 200, 250, 90, 20) GUICtrlSetOnEvent(-1, "decrement") GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked") GUISetState(@SW_SHOW) Func decrement() ....... EndFunc Func increment() ..... EndFunc Func STARTClicked() main() GUICtrlSetData( $status, "Started") EndFunc Func STOPClicked() GUICtrlSetData( $status, "Stopped") EndFunc While 1 Sleep(1000) ; Idle around WEnd
hannes08 Posted February 27, 2011 Posted February 27, 2011 Hi Expansion, you could do a GUISetState(@SW_DISABLE). Until the "Select Folder" dialogue has finished. Regards, Hannes Regards,Hannes[spoiler]If you can't convince them, confuse them![/spoiler]
Expansion Posted February 27, 2011 Author Posted February 27, 2011 Hannes123, I don't want to disable the GUI window while main() is waiting for that window to appear. In fact, I want the opposite. I want to be able to use the GUI [clicking buttons, setting edit controls etc] while main() waiting for that window.
PsaltyDS Posted February 27, 2011 Posted February 27, 2011 AutoIt is single threaded, the only way would be to spin off a child process with Run(). There are examples posted where the the script launches another instance of itself with command line options to perform just the blocking functions. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Expansion Posted February 27, 2011 Author Posted February 27, 2011 (edited) This sounds complicated, because everytime it finds that window, main() has to update some things on the GUI. Edited February 27, 2011 by Expansion
MvGulik Posted February 27, 2011 Posted February 27, 2011 WinWaitWinExists "Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions.""The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014) "Believing what you know ain't so" ... Knock Knock ...Â
John Posted February 27, 2011 Posted February 27, 2011 You can do it this way: HotKeySet("^1", "main") HotKeySet("^2", "block") Send("^2") main() Func main() MsgBox(0,"","main") EndFunc Func block() HotKeySet("^2") ;Either unset the hotkey or ensure it will not interfere. ; <do your block routine here, which never returns but loops forever like main> ; For now this is testing code While 1 $re=MouseGetPos() ToolTip($re[0] & " : " & $re[1], $re[0], $re[1]) WEnd EndFunc Sleep(2000000) Note that any modal dialogs, as demonstrated with the MsgBox(), from either function will pause both, but you can have as many normal (infinite) loops with routines running simultaneously as you wish without interference with each other this way. No need for process level duplication.
John Posted February 27, 2011 Posted February 27, 2011 Scratch that, further testing shows me to be wrong.
PsaltyDS Posted February 28, 2011 Posted February 28, 2011 I thought the OP was meaning to run FileSelectFolder() and keep the GUI responsive while it was up. If the "Select Folder" window already comes from a different process then you just need to do this: expandcollapse popup#include <GUIConstantsEx.au3> #include <TreeviewConstants.au3> #include <WindowsConstants.au3> #include <EditConstants.au3> #include <StaticConstants.au3> #include <GuiButton.au3> #include <Array.au3> Opt("GUIOnEventMode", 1) ; Change to OnEvent mode Opt("MustDeclareVars", 1) Global $mainwindow, $treeview_hwnd, $f_WaitForFolder = False Global $start, $stop, $increment, $decrement, $status $mainwindow = GUICreate("My GUI edit", 600, 300) GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked") $status = GUICtrlCreateEdit("status", 0, 280, 600, 20, $ES_READONLY) $start = GUICtrlCreateButton("Start", 300, 250, 90, 20) GUICtrlSetOnEvent(-1, "STARTClicked") $stop = GUICtrlCreateButton("Stop", 400, 250, 90, 20) GUICtrlSetOnEvent(-1, 'STOPClicked') $increment = GUICtrlCreateButton("+", 100, 250, 90, 20) GUICtrlSetOnEvent(-1, "increment") $decrement = GUICtrlCreateButton("-", 200, 250, 90, 20) GUICtrlSetOnEvent(-1, "decrement") GUISetState(@SW_SHOW) While 1 If $f_WaitForFolder Then $treeview_hwnd = WinWait("Select Folder", "", 1) If $treeview_hwnd Then $f_WaitForFolder = False GUICtrlSetData($status, "Got handle: " & $treeview_hwnd) EndIf EndIf Sleep(20) ; Idle around WEnd Func decrement() ; ....... EndFunc ;==>decrement Func increment() ; ..... EndFunc ;==>increment Func STARTClicked() $f_WaitForFolder = True GUICtrlSetData($status, "Started") EndFunc ;==>STARTClicked Func STOPClicked() $f_WaitForFolder = False GUICtrlSetData($status, "Stopped") EndFunc ;==>STOPClicked Func CLOSEClicked() Exit EndFunc ;==>CLOSEClicked Fixed the bad structure of the OP's script, so it can be read with less confusion. The problem was going into the event function STARTClicked() and not getting out again as soon as possible. There should be no Wait functions, Sleeps, or length processes in any event function. An event function should handle an event quickly and return so as not to block other events. The fix here was to have the event functions only switch a flag variable that controls the window check in the main loop. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Expansion Posted March 1, 2011 Author Posted March 1, 2011 (edited) Thank you guys! PsaltyDS, I've followed your idea, but I haven't managed to make it work with GUI as it does without the GUI, yet. Mainly because I don't have a debugger. I really need a line-by-line execution + a variable monitor, in order to correct it. This script has the following purpose: It waits for a specific treeview, and when it detects it, it creates a folder like this: $root & $folder & $number [ex. "C:\My PF\Test\temp \New\ 0" ] and autoselects this folder in the treeview. Eventually, it increments the $number and waits for the next treeview. Problems that I have: [partially solved with sleep()] The TreeView, detects newly created folder after a period of time. And TreeView autoselection might fail, if the folder isn't yet detected. [not solved] it seems that I have to implement something that considers PID too, because the treeview's parent is not a child of the main app's window and I can't use the main app's window handle, and I might get wrong triggering with treeviews from other apps. [not solved] after merging the "console" script with the GUI, this fails to work, and I haven't discovered my mistakes yet. I really need a line-by-line debugger. Here's the actual complete code of the whole script. expandcollapse popup#include <GUIConstantsEx.au3> #include <TreeviewConstants.au3> #include <WindowsConstants.au3> #include <EditConstants.au3> #include <StaticConstants.au3> #include <GuiButton.au3> #include <Array.au3> Opt("GUIOnEventMode", 1) ; Change to OnEvent mode Opt("MustDeclareVars", 1) Global $mainwindow, $f_WaitForFolder = False Global $start, $stop, $increment, $decrement, $status, $pause Global $handlegui, $rootgui, $foldergui, $numbergui, $readonlypath Global $handle, $root, $folder, $number Global $OSType Func MakePath($root,$folder,$number) dim $path If $number<10 Then $path=$root&"\"&$folder&"\"&"0"&$number;&"\0" Else $path=$root&"\"&$folder&"\"&$number;&"\0" EndIf return $path EndFunc Func TreeViewArray($path) Dim $patharray, $temp , $treeviewarray $patharray=StringSplit ( $path, "\", 2) ;2 omits the first element, because it stores the number of strings returned $patharray[0]=$patharray[0]&")" $temp=_ArrayToString($patharray, "|") if $OSType==1 Then $treeviewarray="Desktop|Computer|Local Disk ("&$temp return $treeviewarray Elseif $OSType==2 Then $treeviewarray="Desktop|My Computer|Local Disk ("&$temp return $treeviewarray Else return 100 endif EndFunc Func SelectTreeView($treeview_hwnd,$treeviewpath) Dim $return, $i,$treeviewarray, $temp, $safe ;MsgBox(4096, "Error",$treeviewpath ) $treeviewarray=StringSplit ( $treeviewpath ,"|" , 2 ) ;MsgBox(4096, "Error",UBound($treeviewarray)) For $i = 1 To UBound($treeviewarray)-1 Step +1 $temp=_ArrayToString($treeviewarray, "|" , 0 , $i) ;MsgBox(4096, "temp",$temp) $safe=ControlTreeView ( $treeview_hwnd, "", "", "Select", $temp) If @error Then ;MsgBox(4096, "Error", "SelectTreeView error") endif Sleep(10) Next Endfunc Func GetOS() If @OSVersion=="WIN_7" Then $OSType=1 ElseIf @OSVersion=="WIN_XP" Then $OSType=2 Else MsgBox(4096, "OS not Win7 nor WinXP") EndIf EndFunc Func SetNumber($value) Dim $value $number=$value EndFunc Func IncrementNumber() $number=$number+1 EndFunc Func DecrementNumber() $number=$number-1 EndFunc Func main($treeview_hwnd) dim $safe=DirCreate(MakePath($root,$folder,$number)) $safe=DirCreate(MakePath($root,$folder,$number+1)) ;make the next folder in advance, so that treeview selection doesn't wait if $safe==1 Then ;debug zone for treeview selection ;SelectTreeView($treeview_hwnd, "#1|#1|#1") ;SelectTreeView($treeview_hwnd, "Desktop|My Computer") ;SelectTreeView($treeview_hwnd, "Desktop|My Computer|Local Disk (C:)") ;SelectTreeView($treeview_hwnd, "Desktop|My Computer|Local Disk (C:)|My PF|") ;SelectTreeView($treeview_hwnd, "Desktop|My Computer|Local Disk (C:)|My PF|Test|") ;Desktop|My Computer|Local Disk (C:)|My PF|Test|temp|New|00 Sleep(100) SelectTreeView($treeview_hwnd, "Desktop|My Computer") SelectTreeView($treeview_hwnd, "Desktop|My Computer") ;just to make sure that it selects it, because sometimes it misses it. if $number==0 Then ;first time has to wait longer so that treeview sees the folder sleep(2000) Endif SelectTreeView($treeview_hwnd, TreeViewArray(MakePath($root,$folder,$number))) while WinExists($treeview_hwnd) sleep(100) wend IncrementNumber() GUICtrlSetData($handlegui, $handle) GUICtrlSetData($rootgui, $root) GUICtrlSetData($foldergui, $folder) GUICtrlSetData($numbergui, $number) GUICtrlSetData($readonlypath, MakePath($root,$folder,$number)) Else MsgBox(4096, "Error","DirCreate") EndIf EndFunc $mainwindow = GUICreate("My GUI edit", 600, 300) GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked") GUICtrlCreateLabel ( "handle", 10, 10 ) $handlegui = GUICtrlCreateEdit("" , 50, 8, 200, 20) ;isn't used yet, because it seems that the treeview's parent isn't a child of the main app window, I have to implement something that checks PID instead, in order not to interfere GUICtrlCreateLabel ( "root", 10, 80 ) $rootgui = GUICtrlCreateEdit("" , 50, 40, 480, 80, $ES_OEMCONVERT) GUICtrlCreateLabel ( "folder", 10, 133 ) $foldergui = GUICtrlCreateEdit("" , 50, 130, 200, 20) GUICtrlCreateLabel ( "number", 10, 163 ) $numbergui = GUICtrlCreateEdit("" , 50, 161, 200, 20, $ES_NUMBER) GUICtrlCreateLabel ( "readonly path", 10, 203 ) $readonlypath= GUICtrlCreateEdit("" , 90, 191, 440, 40, $ES_READONLY) $status = GUICtrlCreateEdit("status", 0, 280, 600, 20, $ES_READONLY) $start = GUICtrlCreateButton("Start", 300, 250, 90, 20) GUICtrlSetOnEvent(-1, "STARTClicked") $stop = GUICtrlCreateButton("Stop", 400, 250, 90, 20) GUICtrlSetOnEvent(-1, 'STOPClicked') $increment = GUICtrlCreateButton("+", 100, 250, 90, 20) GUICtrlSetOnEvent(-1, "increment") $decrement = GUICtrlCreateButton("-", 200, 250, 90, 20) GUICtrlSetOnEvent(-1, "decrement") $pause = GUICtrlCreateButton( "Pause", 500, 250, 90, 20) GUISetState(@SW_SHOW) ;;;;;;;init stuff GetOS() GUICtrlSetData($rootgui, "C:\My PF\Test\temp") GUICtrlSetData($foldergui,"New") GUICtrlSetData($numbergui, "0") ;;;;;;; While 1 If $f_WaitForFolder Then dim $treeview_hwnd = WinWait("Select Folder", "", 1) If $treeview_hwnd Then $f_WaitForFolder = False GUICtrlSetData($status, "Got handle: " & $treeview_hwnd) main($treeview_hwnd) EndIf EndIf Sleep(20) ; Idle around WEnd Func decrement() DecrementNumber() GUICtrlSetData($readonlypath, MakePath($root,$folder,$number)) EndFunc ;==>decrement Func increment() IncrementNumber() GUICtrlSetData($readonlypath, MakePath($root,$folder,$number)) EndFunc ;==>increment Func STARTClicked() $f_WaitForFolder = True $root=$rootgui ;example: "C:\My PF\Test\temp" $folder=$foldergui ;example: "New" SetNumber($numbergui) GUICtrlSetData($readonlypath, MakePath($root,$folder,$number)) GUICtrlSetData($status, "Started") EndFunc ;==>STARTClicked Func STOPClicked() $f_WaitForFolder = False GUICtrlSetData($status, "Stopped") EndFunc ;==>STOPClicked Func CLOSEClicked() Exit EndFunc ;==>CLOSEClicked Edited March 1, 2011 by Expansion
PsaltyDS Posted March 1, 2011 Posted March 1, 2011 Trying to read a scrambled script like that just isn't worth it. I straightened it out once to see what was going on; I'm not going to do again with an even longer version. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Expansion Posted March 2, 2011 Author Posted March 2, 2011 I'll do that, just tell me what's the most effective way to debug in AutoIt. I can't just post MsgBox commands everywhere.
PsaltyDS Posted March 2, 2011 Posted March 2, 2011 (edited) I like ConsoleWrite() and then running it in SciTE to see the console outputs. If there will be LOTS of logging info, then I prefer _FileWriteLog() to send it to a file, which also adds Date/Time stamps for you. Or there is _DebugOut(). Stepped execution is not available. There are debug options in the Tools menu of SciTE4AutoIt3 but I find them excessive, preferring to only set up temporary debug outputs with ConsoleWrite() or _FileWriteLog(). The best practice layout of a script to make it easier for people to read, debug, and maintain is: 1. All compiler directives (i.e. #AutoIt3Wrapper_au3check_parameters) 2. All #includes (i.e. #include <Array.au3>) 3. All Global Opt() statements 4. All Global variable declarations 5. Initial script code 6. All locally declared functions grouped together at the bottom 7. Liberal use of comments throughout. This things are not technically required by the language, but reduce the pain of reviewing lots of other people's code while trying to help them. Edited March 2, 2011 by PsaltyDS Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Expansion Posted March 2, 2011 Author Posted March 2, 2011 Thank you, PsaltyDS. I've managed to correct the problems using ConsoleWrite.
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