Sign in to follow this  
Followers 0
dJRa

GUIOnEventMode doesn_t work in loop

16 posts in this topic

Hello!

In a script (with Opt("GUIOnEventMode", 1)) I start an external program inside a "for $i" loop.

I use ShellExecuteWait for not to start many instancies of the external program at the same time, but to have them start one after the other.

My problem is, if I do it that way, the Gui doesn't react on events, as the script is paused while the external program is running. So I dont't have the control over my script, once the loop with ShellExecuteWait is started.

How can I let the external program start one after the other, without loosing control over the script?

Share this post


Link to post
Share on other sites



ShellExecuteWait

--------------------------------------------------------------------------------

Runs an external program using the ShellExecute API and pauses script execution until it finishes.

ShellExecute

--------------------------------------------------------------------------------

Runs an external program using the ShellExecute API.

Good ol' help :)


SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites

I know. But if I use SchellExecute, many instancies of the program run at the same time, because the loop goes on (as I already said). And that is exactly, what I do not want.

I'm looking for a way of starting only one instancy at the same time without the script loosing the ability to react on pressed buttons (-->events).

Share this post


Link to post
Share on other sites

So check for the process yourself and watch for it to end before you move on to the next one.

Share this post


Link to post
Share on other sites

The launched process should be under running processes in windows --> check using:

ProcessList ( ["name"] )

If so you can use

ProcessExists ( "process" )
to poll if it's still running before launching the next instance.

More info on these functions is in the help file incl. examples on how to use them.

Grtz,

Rick

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

That's what I already tried: but if I do a loop like this one

For $i = 0 to $Filecount
    ShellExecute("process.exe",$command[$i])
    While ProcessExists("process.exe")
        Sleep(100)
    WEnd
Next

it has exactly the same effect as "ShellExecuteWait": while the processes don't run at the same time, my GUI again doesn't react on events.

I have no idea what to do.

How can I have the GUI react on events in such a while-wend loop?

With "Opt("GUIOnEventMode", 1) " it works in the other parts of the script, but not in this one.

EDIT: It also doesn't change anything, if I have my loop without the "Sleep(100)"-command.

Edited by dJRa

Share this post


Link to post
Share on other sites

What if you launch your AutoIT script and the loop code from a batch file? You could even launch the AutoIT gui code and the loop code from another AutoIT program. That would make them independent, wouldn't it?

I have no idea what to do.


...by the way, it's pronounced: "JIF"... Bob Berry --- inventor of the GIF format

Share this post


Link to post
Share on other sites

I didn't try it, but I suppose, that produces exactly the same problem.

Share this post


Link to post
Share on other sites

If you post your code, we can see exactly what you are doing. This may help to provide a solution.

Share this post


Link to post
Share on other sites

Here it is. Simple script and not yet finished, don't laugh at it. :">

As you see, it is a simple GUI for lame. I know there are many of them on the net, but I want to do my own.

#include <GUIConstants.au3>
#include <GuiListView.au3>

Global $DefaultStatus = "Ready..."
Global $gaDropFiles[1]
Global Const $WM_DROPFILES = 0x233

Opt("GUIOnEventMode", 1)

$MainWindow = GUICreate("Script",600,500,-1,-1,-1,$WS_EX_ACCEPTFILES)
$FileMenu = GUICtrlCreateMenu ("&File")
$FileItem = GUICtrlCreateMenuItem ("Add File",$FileMenu)
$RemoveItem = GUICtrlCreateMenuItem ("Remove File",$FileMenu)
$Separator1 = GUICtrlCreateMenuItem ("",$FileMenu)
$ExitItem = GUICtrlCreateMenuItem ("End",$FileMenu)
$RecentFilesMenu = GUICtrlCreateMenu ("Recent Files",$FileMenu,1)
$ViewMenu = GUICtrlCreateMenu("View")
$ViewStatusItem = GUICtrlCreateMenuItem ("Statusbar",$ViewMenu)
GUICtrlSetState(-1,$GUI_CHECKED)
$HelpMenu = GUICtrlCreateMenu ("?")
$InfoItem = GUICtrlCreateMenuItem ("Info",$HelpMenu)

$OKButton = GUICtrlCreateButton ("OK",100,440,70,20)
GUICtrlSetState(-1,$GUI_FOCUS)
$CancelButton = GUICtrlCreateButton ("Cancel",230,440,70,20)
$StatusLabel = GUICtrlCreateLabel ($defaultstatus,0,465,600,16,BitOr($SS_SIMPLE,$SS_SUNKEN))
$ListView = GUICtrlCreateListView ("Filename|Status", 1, 1, 600, 350)
_GUICtrlListViewSetColumnWidth ( -1, 0, 500)
_GUICtrlListViewSetColumnWidth ( -1, 1, 96)
GuiCtrlSetState(-1,$GUI_DROPACCEPTED)
GUICtrlCreateLabel ("LAME-Parameter:",  1, 383)
$Par1 = GUICtrlCreateInput("-V2",88,380,513,20)

GUICtrlSetOnEvent($FileItem, "FileItem")
GUICtrlSetOnEvent($ViewStatusItem, "ViewStatusItem")
GUICtrlSetOnEvent($InfoItem, "InfoItem")
GUICtrlSetOnEvent($OKButton, "RunLame")
GUICtrlSetOnEvent($CancelButton, "CancelButton")
GUICtrlSetOnEvent($ExitItem, "CancelButton")
GUISetOnEvent($GUI_EVENT_CLOSE, "CancelButton")
GUIRegisterMsg($WM_DROPFILES, "WM_DROPFILES_FUNC")

GUISetState()

While 1
    Sleep(100)
WEnd

Func FileItem()
    $File = FileOpenDialog("Dateien auswählen...",@ScriptDir,"Wave (*.wav)",4)
    If @error <> 1 Then
        GUICtrlCreateMenuitem ($File,$RecentFilesMenu)
        GuiCtrlCreateListViewItem($File,$ListView)
    EndIf
EndFunc

Func ViewStatusItem()
    If BitAnd(GUICtrlRead($viewstatusitem),$GUI_CHECKED) = $GUI_CHECKED Then
        GUICtrlSetState($viewstatusitem,$GUI_UNCHECKED)
        GUICtrlSetState($statuslabel,$GUI_HIDE)
    Else
        GUICtrlSetState($viewstatusitem,$GUI_CHECKED)
        GUICtrlSetState($statuslabel,$GUI_SHOW)
    EndIf   
EndFunc

Func InfoItem()
    Msgbox(0,"Info","Script")
EndFunc

Func CancelButton()
    Exit
EndFunc

Func WM_DROPFILES_FUNC($hWnd, $msgID, $wParam, $lParam)
    Local $nSize, $pFileName
    Local $nAmt = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", 0xFFFFFFFF, "ptr", 0, "int", 255)
    For $i = 0 To $nAmt[0] - 1
        $nSize = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", 0, "int", 0)
        $nSize = $nSize[0] + 1
        $pFileName = DllStructCreate("char[" & $nSize & "]")
        DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", DllStructGetPtr($pFileName), "int", $nSize)
        ReDim $gaDropFiles[$i + 1]
        $gaDropFiles[$i] = DllStructGetData($pFileName, 1)
        If StringRight ($gaDropFiles[$i],4)=".wav" Then
            GuiCtrlCreateListViewItem($gaDropFiles[$i],$ListView)
        EndIf
        $pFileName = 0
    Next
EndFunc 

Func RunLame()
        $Par2 = GUICtrlRead($Par1)
        $Filecount=_GUICtrlListViewGetItemCount($ListView)-1
        For $i = 0 to $Filecount
            $Par3 = _GUICtrlListViewGetItemText($ListView,$i,0)
            $command = $Par2&" """&$Par3&""" """&StringLeft($Par3,StringLen($Par3)-3)&"mp3"""
            ShellExecute("lame.exe",$command)
            While ProcessExists("lame.exe")
            WEnd
                    Next
EndFunc

My problem is in the Function "RunLame". Within the While-Wend-Loop or with ShellExecuteWait, I can't cancel the script by pressing "Cancel" or a click on the "X" in the upper right angle.

Share this post


Link to post
Share on other sites

Here it is. Simple script and not yet finished, don't laugh at it. :">

As you see, it is a simple GUI for lame. I know there are many of them on the net, but I want to do my own.

#include <GUIConstants.au3>
#include <GuiListView.au3>

Global $DefaultStatus = "Ready..."
Global $gaDropFiles[1]
Global Const $WM_DROPFILES = 0x233

Opt("GUIOnEventMode", 1)

$MainWindow = GUICreate("Script",600,500,-1,-1,-1,$WS_EX_ACCEPTFILES)
$FileMenu = GUICtrlCreateMenu ("&File")
$FileItem = GUICtrlCreateMenuItem ("Add File",$FileMenu)
$RemoveItem = GUICtrlCreateMenuItem ("Remove File",$FileMenu)
$Separator1 = GUICtrlCreateMenuItem ("",$FileMenu)
$ExitItem = GUICtrlCreateMenuItem ("End",$FileMenu)
$RecentFilesMenu = GUICtrlCreateMenu ("Recent Files",$FileMenu,1)
$ViewMenu = GUICtrlCreateMenu("View")
$ViewStatusItem = GUICtrlCreateMenuItem ("Statusbar",$ViewMenu)
GUICtrlSetState(-1,$GUI_CHECKED)
$HelpMenu = GUICtrlCreateMenu ("?")
$InfoItem = GUICtrlCreateMenuItem ("Info",$HelpMenu)

$OKButton = GUICtrlCreateButton ("OK",100,440,70,20)
GUICtrlSetState(-1,$GUI_FOCUS)
$CancelButton = GUICtrlCreateButton ("Cancel",230,440,70,20)
$StatusLabel = GUICtrlCreateLabel ($defaultstatus,0,465,600,16,BitOr($SS_SIMPLE,$SS_SUNKEN))
$ListView = GUICtrlCreateListView ("Filename|Status", 1, 1, 600, 350)
_GUICtrlListViewSetColumnWidth ( -1, 0, 500)
_GUICtrlListViewSetColumnWidth ( -1, 1, 96)
GuiCtrlSetState(-1,$GUI_DROPACCEPTED)
GUICtrlCreateLabel ("LAME-Parameter:",  1, 383)
$Par1 = GUICtrlCreateInput("-V2",88,380,513,20)

GUICtrlSetOnEvent($FileItem, "FileItem")
GUICtrlSetOnEvent($ViewStatusItem, "ViewStatusItem")
GUICtrlSetOnEvent($InfoItem, "InfoItem")
GUICtrlSetOnEvent($OKButton, "RunLame")
GUICtrlSetOnEvent($CancelButton, "CancelButton")
GUICtrlSetOnEvent($ExitItem, "CancelButton")
GUISetOnEvent($GUI_EVENT_CLOSE, "CancelButton")
GUIRegisterMsg($WM_DROPFILES, "WM_DROPFILES_FUNC")

GUISetState()

While 1
    Sleep(100)
WEnd

Func FileItem()
    $File = FileOpenDialog("Dateien auswählen...",@ScriptDir,"Wave (*.wav)",4)
    If @error <> 1 Then
        GUICtrlCreateMenuitem ($File,$RecentFilesMenu)
        GuiCtrlCreateListViewItem($File,$ListView)
    EndIf
EndFunc

Func ViewStatusItem()
    If BitAnd(GUICtrlRead($viewstatusitem),$GUI_CHECKED) = $GUI_CHECKED Then
        GUICtrlSetState($viewstatusitem,$GUI_UNCHECKED)
        GUICtrlSetState($statuslabel,$GUI_HIDE)
    Else
        GUICtrlSetState($viewstatusitem,$GUI_CHECKED)
        GUICtrlSetState($statuslabel,$GUI_SHOW)
    EndIf   
EndFunc

Func InfoItem()
    Msgbox(0,"Info","Script")
EndFunc

Func CancelButton()
    Exit
EndFunc

Func WM_DROPFILES_FUNC($hWnd, $msgID, $wParam, $lParam)
    Local $nSize, $pFileName
    Local $nAmt = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", 0xFFFFFFFF, "ptr", 0, "int", 255)
    For $i = 0 To $nAmt[0] - 1
        $nSize = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", 0, "int", 0)
        $nSize = $nSize[0] + 1
        $pFileName = DllStructCreate("char[" & $nSize & "]")
        DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", DllStructGetPtr($pFileName), "int", $nSize)
        ReDim $gaDropFiles[$i + 1]
        $gaDropFiles[$i] = DllStructGetData($pFileName, 1)
        If StringRight ($gaDropFiles[$i],4)=".wav" Then
            GuiCtrlCreateListViewItem($gaDropFiles[$i],$ListView)
        EndIf
        $pFileName = 0
    Next
EndFunc 

Func RunLame()
        $Par2 = GUICtrlRead($Par1)
        $Filecount=_GUICtrlListViewGetItemCount($ListView)-1
        For $i = 0 to $Filecount
            $Par3 = _GUICtrlListViewGetItemText($ListView,$i,0)
            $command = $Par2&" """&$Par3&""" """&StringLeft($Par3,StringLen($Par3)-3)&"mp3"""
            ShellExecute("lame.exe",$command)
            While ProcessExists("lame.exe")
            WEnd
                    Next
EndFunc

My problem is in the Function "RunLame". Within the While-Wend-Loop or with ShellExecuteWait, I can't cancel the script by pressing "Cancel" or a click on the "X" in the upper right angle.

I cant really test as I am at work right now. However, what about running a cmd shell outside of your for loop, then sending commands to the window within your loop? I dont use lame myself, so not sure thats appropriate, but your code (even if it could wait between commands) would always create a new "instance" of a shell.

Share this post


Link to post
Share on other sites

I'm not sure I understood you right.

In a CMD-Shell, I also can't send all of my commands "at once" (and that will happen if I do it out of the for-loop).

Before sending a new command, I would always have to check (within the for-loop), if the command I sent before, is already finished. And for that, again I would need a While-Wend-loop. So it would be exactly the same.

Or is it not, what you mean?

Share this post


Link to post
Share on other sites

I'm not sure I understood you right.

In a CMD-Shell, I also can't send all of my commands "at once" (and that will happen if I do it out of the for-loop).

Before sending a new command, I would always have to check (within the for-loop), if the command I sent before, is already finished. And for that, again I would need a While-Wend-loop. So it would be exactly the same.

Or is it not, what you mean?

Yeah, you still will need a while loop. I think you understand what I was writing. Perhaps it isnt entirely appropriate with Lame. Ill have to try it on a system at home to see exactly what the behavior is. To be clear, though, you are saying you get several instances of the program, rather than one that takes all the commands, correct? So the desired outcome would be for the function to feed as string of commands to the shell (Lame.exe)?

Share this post


Link to post
Share on other sites

With the While-Wend-loop, the programs start one after the other, but I can't cancel the script, as GUIOnEventMode doesn't seem to work.

Without the While-Wend-loop, theoretically I can cancel the script, but the instancies of lame all start at approximately the same time. So if I cancel the script, it is too late, as then, a large part of the for-loop has already passed.

Even if I would manage to feed all commands in one string to the shell (which wouldn't work with lame, I suppose), it is not what I desire, as in that case, I also wouldn't have a possibility to stop the script, before all the commands are finished.

Of course, I could close the shell and all processes would stop, but then I wouldn't new, which files are already converted and which not.

I'm sure, there is a possibility, to react on GUI-events even withhin the While-Wend-loop. I just couldn't find the trick yet.

Share this post


Link to post
Share on other sites

Did you think of changing your approach...

Have a function pass the file name / Lame commands to some other function that handles one Lame-session at the time.

Anyways - just a thought.

Share this post


Link to post
Share on other sites

Here's an example of a GUI in Event Mode, that remains responsive to controls while running a sequence of processes:

#include <GuiConstants.au3>

Opt("GuiOnEventMode", 1)
Global $iCnt = 3, $PID = "", $iTimer

GUICreate("Test", 300, 200)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Quit")
$Label_1 = GUICtrlCreateLabel("Creating " & $iCnt & " more instances of Notepad...", 10, 10, 280, 20)
GUICtrlCreateButton("Time", 10, 65, 100, 100)
GUICtrlSetOnEvent(-1, "_Time")
GUISetState()

While 1
    If Not ProcessExists($PID) Then
        If $iCnt = 0 Then Exit
        $PID = Run("notepad.exe")
        $iTimer = TimerInit()
        $iCnt -= 1
        GUICtrlSetData($Label_1, "Creating " & $iCnt & " more instances of Notepad...")
    EndIf
    Sleep(20)
WEnd

Func _Quit()
    ProcessClose($PID)
    Exit
EndFunc

Func _Time()
    If ProcessExists($PID) Then MsgBox(64, "Time", "Current window has been up for " & _
            Round(TimerDiff($iTimer) / 1000, 2) & " seconds.", 2)
EndFunc

Hope that helps...

:)


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

Share this post


Link to post
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
Sign in to follow this  
Followers 0