Jump to content

Force Function to wait for secondary Gui To Return (Or set a value to a variable)


rm4453
 Share

Recommended Posts

Hello,

 

I am attempting to force one of my functions to wait for a secondary GUI to return a variable, or set a variable value to anything other than blank

I keep running into the issue of my main GUI continuing on in it's script execution, without waiting for secondary GUI to return / modify the variable.


I need the user to be able to select an option from a drop down combo box, that pops over my main GUI.

I would use an inputbox, however that does not have an option for a drop down combo box.

 

I am in the middle of a function that is called by my main GUI when I am attempting to do this.

I am very new to multi GUI setups, and would appreciate any and all help provided.

 

*Due to NDA on this project I can only share minimal code that I have tried please see below:

 

$alertForm = GUICreate("Alert Type?", 186, 110, 192, 124)
$alertType = GUICtrlCreateCombo("", 32, 40, 121, 25)
GUICtrlSetData(-1, "APPD|CPU|DISK SPACE|MEMORY|NETWORK DOWN|NETWORK PACKET LOSS|NETWORK RESPONSE|NETWORK UTILIZATION|SERVER DOWN|SITESCOPE|SPLUNK|STORAGE|OTHER")
$alertLabel = GUICtrlCreateLabel("Please Select Alert Type:", 32, 18, 123, 17)
$alertSub = GUICtrlCreateButton("SELECT", 56, 72, 73, 25)
GUISetState(@SW_HIDE)

$nMsg = GUIGetMsg(1)
Switch $nMsg[1]
    Case $Template_Generator
        Switch $nMsg[0]
            Case $generate
                CPU()
            
    EndSwitch
    
    Case $alertForm
        Switch $nMsg[0]
            Case $GUI_EVENT_CLOSE
;~              MsgBox("", "", "HERE - EXIT")
                GUISetState(@SW_SHOW, $Template_Generator)
                GUISetState(@SW_HIDE, $alertForm)
            Case $alertSub
                $alert = GUICtrlRead($alertType)
                GUISetState(@SW_SHOW, $Template_Generator)
                GUISetState(@SW_HIDE, $alertForm)
;~              MsgBox("", "", $alert)
                Return $alert

        EndSwitch

EndSwitch

;~ CPU WILL EVENTUALLY CALL ALERT WITH CURRENT SETUP

Func ALERT()

    $wPos = WinGetPos($Template_Generator)
    WinMove($alertForm, "", $wPos[0] + Int($wPos[2] / 2) - Int(250 / 2), $wPos[1] + Int($wPos[3] / 2) - Int(190 / 2))
    GUISetState(@SW_SHOW, $alertForm)
    GUISetState(@SW_HIDE, $Template_Generator)

    $alert = ""
    MsgBox("", "", WinGetState($Template_Generator))
    $continue = False
    While $continue = False
        If WinGetState($Template_Generator) < 2 Then ;~ Not quite sure how this works or what number "2" should be for the state of $Template_Generator
            $continue = True
        EndIf
        Sleep(25)
    WEnd

EndFunc   ;==>ALERT

 

Edited by rm4453
Fixed Code *Forgot To Include All
Link to comment
Share on other sites

Hey,

Just a thought.

Can you not set that variable an initial certain value that shouldn't be and sleep while it is still set as that. Checking for a possible value after each sleep. Loop until value changes.

I hope what I wrote is meaningful. Example of what I am trying to say (Code may not be AutoIt syntax :) )

$sText = "Can't be this"

$iMaxSleepTime = 10000

$iSleep = 0

do while $sText <> "Can't be this"

    sleep(1000)

    $iSleep += 1000

    if $iSleep > $iMaxSleepTime then ExitLoop

loop

 

Edited by GokAy
Added Example
Link to comment
Share on other sites

3 minutes ago, GokAy said:

Hey,

Just a thought.

Can you not set that variable an initial certain value that shouldn't be and sleep while it is still set as that. Checking for a possible value after each sleep. Loop until value changes.

I hope what I wrote is meaningful.

No worries, I appreciate the input, I have already tried that, however I still run into the issue where it doesn't wait for the return before continuing on

Link to comment
Share on other sites

3 minutes ago, GokAy said:

Edit'ed first post with an example, are you doing a similar thing? Maybe you should post a snippet of the part that doesn't work when you tried the idea for others to comment.

The part of my code which is a while loop is doing that in another way as the secondary GUI should set the continue var to TRUE, however here is an example checking just the text itself to decide if it should continue:

 

;~ ALERT SUB BECOMES THIS WITH THE MODICIFACTIONS:

Case $alertSub
                    $alert = GUICtrlRead($alertType)
;~                  MsgBox("", "", $alert)
                    Return $alert
                    
;~ ALERT BECOMES THIS WITH THE MODIFICATIONS:

Func ALERT()

$wPos = WinGetPos($Template_Generator)
    WinMove($alertForm, "", $wPos[0] + Int($wPos[2] / 2) - Int(250 / 2), $wPos[1] + Int($wPos[3] / 2) - Int(190 / 2))
    GUISetState(@SW_SHOW, $alertForm)
    GUISetState(@SW_HIDE, $Template_Generator)

    $alert = ""
    While $alert = ""
        Sleep(25)
    WEnd

    GUISetState(@SW_HIDE, $alertForm)
    GUISetState(@SW_SHOW, $Template_Generator)

EndFunc   ;==>ALERT


*yes I know since alertsub isn't called Return isn't necessary, and the var alert does get updated just a bove it which should trigger moving forward

When I do it this way, the program waits, however the secondary 

Link to comment
Share on other sites

25 minutes ago, GokAy said:

What is the value of the combobox default value? Maybe it is empty string which results in your condition to exit loop becoming true.

Not quite how it works the While is while the var = "", the var isn't set until they press the "SELECT" button in the secondary GUI, and right before the While the var is set to "" which is empty var

Link to comment
Share on other sites

Maybe something like:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Global $g_hWndMain, $g_hWndSubType
Main()

Func Main()
    Local $sAlertSubType
    $g_hWndMain = GUICreate("Main Window", 300, 100)
    Local $idAlertType = GUICtrlCreateCombo("", 20, 40, 260, 25)
        GUICtrlSetData(-1, "APPD|CPU|DISK SPACE")
    GUICtrlCreateLabel("Please Select Alert Type:", 32, 18, 123, 17)
    Local $idAlertSelect = GUICtrlCreateButton("SELECT", 56, 72, 73, 25)
    GUISetState(@SW_SHOW)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $idAlertSelect
                If GUICtrlRead($idAlertType) = "" Then ContinueLoop
                GUISetState(@SW_HIDE, $g_hWndMain)
                $sAlertSubType = _SubType(GUICtrlRead($idAlertType))
                GUISetState(@SW_SHOW, $g_hWndMain)
                MsgBox(4096, "", "$idAlertType = " & GUICtrlRead($idAlertType) & @CRLF & "$sAlertSubType = " & $sAlertSubType)
        EndSwitch
    WEnd
    GUIDelete($g_hWndMain)
EndFunc   ;==>Example

Func _SubType($_sAlertType)
    Local $sAlertType
    Switch $_sAlertType
        Case "APPD"
            $sAlertType = "APPD 1|APPD 2|APP 3"
        Case "CPU"
            $sAlertType = "CPU 1|CPU 2|CPU 3|CPU 4"
        Case "DISK SPACE"
            $sAlertType = "Disk Space 1|Disk Space 2|Disk Space 3|Disk Space 4|Disk Space 5"
    EndSwitch
    Local $sAlertSubType
    $g_hWndSubType = GUICreate("Select", 300, 40)
    Local $idAlertSubType = GUICtrlCreateCombo("Select", 10, 10, 280, 25)
        GUICtrlSetData(-1, $sAlertType)
    GUISetState(@SW_SHOW, $g_hWndSubType)
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ContinueLoop
            Case $idAlertSubType
                $sAlertSubType = GUICtrlRead($idAlertSubType)
                If $sAlertSubType = "Select" Then ContinueLoop
                ExitLoop
        EndSwitch
    WEnd
    GUIDelete($g_hWndSubType)
    Return $sAlertSubType
EndFunc

 

Link to comment
Share on other sites

1 minute ago, Subz said:

Maybe something like:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Global $g_hWndMain, $g_hWndSubType
Main()

Func Main()
    Local $sAlertSubType
    $g_hWndMain = GUICreate("Main Window", 300, 100)
    Local $idAlertType = GUICtrlCreateCombo("", 20, 40, 260, 25)
        GUICtrlSetData(-1, "APPD|CPU|DISK SPACE")
    GUICtrlCreateLabel("Please Select Alert Type:", 32, 18, 123, 17)
    Local $idAlertSelect = GUICtrlCreateButton("SELECT", 56, 72, 73, 25)
    GUISetState(@SW_SHOW)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $idAlertSelect
                If GUICtrlRead($idAlertType) = "" Then ContinueLoop
                GUISetState(@SW_HIDE, $g_hWndMain)
                $sAlertSubType = _SubType(GUICtrlRead($idAlertType))
                GUISetState(@SW_SHOW, $g_hWndMain)
                MsgBox(4096, "", "$idAlertType = " & GUICtrlRead($idAlertType) & @CRLF & "$sAlertSubType = " & $sAlertSubType)
        EndSwitch
    WEnd
    GUIDelete($g_hWndMain)
EndFunc   ;==>Example

Func _SubType($_sAlertType)
    Local $sAlertType
    Switch $_sAlertType
        Case "APPD"
            $sAlertType = "APPD 1|APPD 2|APP 3"
        Case "CPU"
            $sAlertType = "CPU 1|CPU 2|CPU 3|CPU 4"
        Case "DISK SPACE"
            $sAlertType = "Disk Space 1|Disk Space 2|Disk Space 3|Disk Space 4|Disk Space 5"
    EndSwitch
    Local $sAlertSubType
    $g_hWndSubType = GUICreate("Select", 300, 40)
    Local $idAlertSubType = GUICtrlCreateCombo("Select", 10, 10, 280, 25)
        GUICtrlSetData(-1, $sAlertType)
    GUISetState(@SW_SHOW, $g_hWndSubType)
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ContinueLoop
            Case $idAlertSubType
                $sAlertSubType = GUICtrlRead($idAlertSubType)
                If $sAlertSubType = "Select" Then ContinueLoop
                ExitLoop
        EndSwitch
    WEnd
    GUIDelete($g_hWndSubType)
    Return $sAlertSubType
EndFunc

 

This is a great suggestion, however I have to do this inside a func (which is nested inside several other funcs where the initial one is triggered from main GUI button press) that is run from the main GUI which means a "case" can't be triggered on the main GUI as far as I know. ESP considering I can't require the user to click a button to spawn the alert type box, otherwise I would just include the combo box inside the main GUI and call it a day.

I really appreciate the suggestion though!

Link to comment
Share on other sites

Not really sure what you mean, all the code does above is call another window for the sub type and once you select it, it returns to the main window.  If you don't want to use the button you could just change the Case $idAlertSelect to Case $idAlertType, so when the user selects from the combo it spawns the child window.

Link to comment
Share on other sites

Another method would be, secondary GUI send a windows message to primary GUI whenever the combobox value (or input box, or whatever) changes. Requires dll functions for "sendmessage"

Someone can help you with implementing this in AutoIt. I am pasting the required functions I use in VBA.

' In Excel xlsm file
' Constants
Public Const WM_SETTEXT = &HC

' DLL Functions
Public Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

Public Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr

Public Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As Any) As LongPtr

' Usage (ChVideo is an AutoIt a3x script, Window Title is "ChVideo")
Dim ChVideo_hWnd As LongPtr
Dim ChVideo_txt_hWnd As LongPtr
Dim str as string

' First Find ChVideo Window Handle
ChVideo_hWnd = FindWindow(vbNullString, "ChVideo")
' Then the textbox which accepts the sent text
ChVideo_txt_hWnd = FindWindowEx(ChVideo_hWnd, 0, "EDIT", vbNullString)

' Handles return 0 (zero) if not found
' set str
str = "Whatever you want to be sent"
Call SendMessage(ChVideo_txt_hWnd, WM_SETTEXT, 0, str)

' On the receiving side (ChVideo app), there is an enabled textbox, smallest in size, colored as background, no tab stops if possible), that checks for textbox change events. If it changes, executes a command according to text received.

' I only have 1 textbox so this works, might need altering if there are more than 1.

You can get the class type "EDIT" with Spy++ or AutoIt's own Window Info tool.

Edited by GokAy
Added last line
Link to comment
Share on other sites

I would suggest that OP goes back to the drawing board and provide a runable script that clearly shows what the issue he is facing.  Because currently we can continue forever to guess what could be his problem.  I am with  @Subz, I do not understand what OP is trying to achieve and subz's example in my opinion reflects the requirements explained by OP.

Link to comment
Share on other sites

You got multiple ways to wait things to happen.

In your case I would just add wherever you want to wait 

$Myvar = ""
Do
    Sleep(100) 
    ;The stuff I have to check here to change $Myvar
Until $Myvar <> ""

@Zedna is probably right there. 

I mean he probably main by that there are more efficient ways to do that. With parent parameter 8 from GUICreate. 

parent |  [optional] The handle of another previously created window - this new window then becomes a child of that window.

 

In your case you could add a progress bar as a child of parent main GUI so it forces the user to wait. With the "Do" loop to pause. 

Edited by caramen

My video tutorials : ( In construction )  || My Discord : https://discord.gg/S9AnwHw

How to Ask Help ||  UIAutomation From Junkew || WebDriver From Danp2 || And Water's UDFs in the Quote

Spoiler

 Water's UDFs:
Active Directory (NEW 2018-10-19 - Version 1.4.10.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-10-31 - Version 1.3.4.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Link to comment
Share on other sites

13 hours ago, caramen said:

You got multiple ways to wait things to happen.

In your case I would just add wherever you want to wait 

$Myvar = ""
Do
    Sleep(100) 
    ;The stuff I have to check here to change $Myvar
Until $Myvar <> ""

@Zedna is probably right there. 

I mean he probably main by that there are more efficient ways to do that. With parent parameter 8 from GUICreate. 

parent |  [optional] The handle of another previously created window - this new window then becomes a child of that window.

 

In your case you could add a progress bar as a child of parent main GUI so it forces the user to wait. With the "Do" loop to pause. 

Here is an attached example gif with all blurred out that I can't let you see.

Child_Gui_Issue.gif.98baabced30df50d7e55f619a0426640.gif

I am currently implementing a while wait here:

 

Func ALERT()

    $wPos = WinGetPos($Template_Generator)
    WinMove($alertForm, "", $wPos[0] + Int($wPos[2] / 2) - Int(250 / 2), $wPos[1] + Int($wPos[3] / 2) - Int(190 / 2))
    GUISetState(@SW_SHOW, $alertForm)
    GUISetState(@SW_HIDE, $Template_Generator)

    $alert = ""
    While $alert = ""
        Sleep(25)
    WEnd

    GUISetState(@SW_HIDE, $alertForm)
    GUISetState(@SW_SHOW, $Template_Generator)

EndFunc   ;==>ALERT

The above code is what is showing the "AlertForm" which is shown at the end of the gif.

As you can see via the gif, it shows up fine, however does not hide itself, and show the generator after select button is pressed.

 

Here is the "AlertForm" GUI code:

 

$alertForm = GUICreate("Alert Type?", 186, 110, 192, 124)
$alertType = GUICtrlCreateCombo("", 32, 40, 121, 25)
GUICtrlSetData(-1, "APPD|CPU|DISK SPACE|MEMORY|NETWORK DOWN|NETWORK PACKET LOSS|NETWORK RESPONSE|NETWORK UTILIZATION|SERVER DOWN|SITESCOPE|SPLUNK|STORAGE|OTHER")
$alertLabel = GUICtrlCreateLabel("Please Select Alert Type:", 32, 18, 123, 17)
$alertSub = GUICtrlCreateButton("SELECT", 56, 72, 73, 25)
GUISetState(@SW_HIDE)

;~ Yes I know this is bad practice however $alert is called on script startup outside of all funcs / gui / before main prog while loop like such:
$alert = ""

$nMsg = GUIGetMsg(1)
    Switch $nMsg[1]
Case $Template_Generator
    Switch $nMsg[0]
    ;~ STUFF DONE HERE ENDS UP AFTER SEVERAL FUNCTIONS CALLING OTHER FUNCTIONS CALLING ALERT()
    Endswitch
Case $alertForm
        Switch $nMsg[0]
            Case $GUI_EVENT_CLOSE
;~              MsgBox("", "", "HERE - EXIT")
                GUISetState(@SW_SHOW, $Template_Generator)
                GUISetState(@SW_HIDE, $alertForm)

            Case $alertSub
                $alert = GUICtrlRead($alertType)
;~              MsgBox("", "", $alert)
                Return $alert
        EndSwitch

    EndSwitch

If I can get the "AlertForm" to hide itself, and the main GUI to continue on without issue, then my issue is resolved - Assuming this happens after the user presses the select button & The var $alert is able to be accessed with the new value from the Main GUI

 

I hope this clarifies, and if there is any further information needed please let me know.

I really appreciate all of the help provided thus far.

Link to comment
Share on other sites

As shown in the example above just return the selection from the second gui, maybe I'm missing something:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Global $g_hWndTemplate_Generator
Main()

Func Main()
    Local $sAlertSubType
    $g_hWndTemplate_Generator = GUICreate("Main Window", 240, 80)
    Local $idGenerate_Template = GUICtrlCreateButton("Generate Template", 20, 20, 200, 40)
    GUISetState(@SW_SHOW)
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $idGenerate_Template
                $sIPAddress = InputBox("Generate Template", "Ip Address:")
                    If @error Then ContinueLoop
                $sLocation = InputBox("Generate Template", "Location:")
                    If @error Then ContinueLoop
                GUISetState(@SW_HIDE, $g_hWndTemplate_Generator)
                $sAlertSubType = _AlertType()
                GUISetState(@SW_SHOW, $g_hWndTemplate_Generator)
                MsgBox(4096, "", "$sIPAddress = " & $sIPAddress & @CRLF & "$sLocation = " & $sLocation & @CRLF & "$sAlertSubType = " & $sAlertSubType)
        EndSwitch
    WEnd
    GUIDelete($g_hWndTemplate_Generator)
EndFunc   ;==>Example

Func _AlertType()
    Local $sAlertSubType
    Local $aWinPos = WinGetPos($g_hWndTemplate_Generator)
    Local $hWndAlertType = GUICreate("Generate Template", 320, 110, $aWinPos[0] + Int($aWinPos[2] / 2) - Int(250 / 2), $aWinPos[1] + Int($aWinPos[3] / 2) - Int(190 / 2))
    GUICtrlCreateLabel("Please Select Alert Type:", 30, 20, 123, 20)
    Local $idAlertSubType = GUICtrlCreateCombo("Select", 30, 45, 280, 25)
        GUICtrlSetData(-1, "APPD|CPU|DISK SPACE|MEMORY|NETWORK DOWN|NETWORK PACKET LOSS|NETWORK RESPONSE|NETWORK UTILIZATION|SERVER DOWN|SITESCOPE|SPLUNK|STORAGE|OTHER")
    GUISetState(@SW_SHOW, $hWndAlertType)
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ContinueLoop
            Case $idAlertSubType
                $sAlertSubType = GUICtrlRead($idAlertSubType)
                If $sAlertSubType = "Select" Then ContinueLoop
                ExitLoop
        EndSwitch
    WEnd
    GUIDelete($hWndAlertType)
    Return $sAlertSubType
EndFunc

 

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...