Jump to content

GUIOnEventMode doesn_t work in loop


dJRa
 Share

Recommended Posts

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?

Link to comment
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 :)

Link to comment
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).

Link to comment
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

Link to comment
Share on other sites

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
Link to comment
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
Link to comment
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.

Link to comment
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.

Link to comment
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?

Link to comment
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)?

Link to comment
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.

Link to comment
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
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...