Jump to content

Close _ArrayDisplay using timeout


Recommended Posts

Hello All,

I use _ArrayDisplay a lot because it's so convenient.

I'd like some input on how to have it timeout and close without the need to click.

I'm sure this is very easy for some people here, but the solution eludes me.

Thank you in advance for any direction.

taurus905

Func _ArrayDisplay(Const ByRef $aArray, $sTitle = Default, $sArrayRange = Default, $iFlags = Default, $vUser_Separator = Default, $sHeader = Default, $iMax_ColWidth = Default)
    #forceref $vUser_Separator
    Local $iRet = __ArrayDisplay_Share($aArray, $sTitle, $sArrayRange, $iFlags, Default, $sHeader, $iMax_ColWidth, 0, False)
    Return SetError(@error, @extended, $iRet)
EndFunc   ;==>_ArrayDisplay

 

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to post
Share on other sites

The easiest way in my opinion is to create another process responsible to close the arraydisplay after a specified delay :

#pragma compile(AutoItExecuteAllowed, true)

#include <Constants.au3>
#include <Array.au3>
#include <WinAPIFiles.au3>

Opt ("MustDeclareVars", True)

Local $aVar = [1,2,3,4,5,6,7,8]
Local $sTitle = "My Array Display Title"

_CreateChild($sTitle, 5000)
_ArrayDisplay($aVar, $sTitle)

Func _CreateChild ($sTitle, $iDuration)
  Local $sTempFile = _WinAPI_GetTempFileName (@TempDir, "~")
  Local $sScript = _
    "#NoTrayIcon" & @CRLF & _
    "While Sleep(100)" & @CRLF & _
    "If WinExists('" & $sTitle & "') Then ExitLoop" & @CRLF & _
    "WEnd" & @CRLF & _
    "Sleep(" & $iDuration & ")" & @CRLF & _
    "If WinExists('" & $sTitle & "') Then WinClose('"  & $sTitle & "')" & @CRLF & _
    "Sleep(200)" & @CRLF & _
    "FileDelete (@ScriptFullPath)"
  FileWrite ($sTempFile, $sScript)
  Run (@AutoItExe & ' /AutoIt3ExecuteScript "' & $sTempFile & '"', @TempDir, @SW_HIDE)
EndFunc

 

Link to post
Share on other sites
4 minutes ago, Nine said:

The easiest way in my opinion is to create another process responsible to close the arraydisplay after a specified delay :

Thank you, Nine.

That's a very elegant solution.

I love to learn new ways to use AutoIt (my favorite for creating tools).

taurus905

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to post
Share on other sites

Hi taurus905 & Nine :
I always liked the AdlibRegister way, which calls the Adlib function only once (maximum) in OP's case, for example :

#include <Array.au3>

Local $aVar = [0,1,2,3,4,5,6,7,8,9]
Local $iTimeOut = 5 ; <=== 5s, change to your wish
Global $g_sTitle = "Close in " & $iTimeOut & "s"

AdlibRegister("MyAdLibFunc", $iTimeOut * 1000)
_ArrayDisplay($aVar, $g_sTitle)
AdlibUnRegister("MyAdLibFunc")

; ...script continuation here

Func MyAdLibFunc()
    If WinExists($g_sTitle) Then
        AdlibUnRegister("MyAdLibFunc")
        WinClose($g_sTitle)
    EndIf
EndFunc   ;==>MyAdLibFunc

But I don't know if it's a good idea to close automatically the new version of ArrayDisplay after a timeout without exiting AutoIt, as the script continues.

What about the eventual big global arrays $_g_ArrayDisplay_aIndex and $_g_ArrayDisplay_aIndexes which could still use a lot of memory ? And the subclassing in ArrayDisplay not being removed, no problem with that ? IDK :frantics:

Edit: the Adlib function could even be shorter in OP's case, something like this :

Func MyAdLibFunc()
    AdlibUnRegister("MyAdLibFunc")
    WinClose($g_sTitle)
EndFunc   ;==>MyAdLibFunc

 

Edited by pixelsearch
Link to post
Share on other sites
6 minutes ago, pixelsearch said:

But I don't know if it's a good idea to close automatically the new version of ArrayDisplay after a timeout without exiting AutoIt, as the script continues.

Hello pixelsearch,

Your input is always welcomed.

In fact, in many cases I want the AutoIt script to continue.

I will test Nine's solution and yours to see which works best for the particular instance.

I appreciate both of your ideas, since I love to have options.

taurus905

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to post
Share on other sites

@pixelsearch  I like your solution, but I have found that in some situations (when the function is truly blocking), the adlib approach (or other timer) will not work.  So this is why I always favor the second-process approach, which will work all the time.  Just my 2 cents BTW.

Link to post
Share on other sites

Hi Nine
Thanks for your input.
I did some tests in 2019 and kept them in a script, so I'll post it now 3 years after, without changing a line in it.
I don't feel like running it again or re-testing but I never considered ArrayDisplay as a blocking function. The AdLib way coupled with ArrayDisplay has been used nearly daily since 2019 by a person I sent a script to,  and he never reported something strange happened, maybe he was lucky :)

#include <Array.au3>
#include <MsgBoxConstants.au3>

Opt("WinTitleMatchMode", -2)    ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase

If ProcessExists("SciTE.exe") = 0 Then
    MsgBox($MB_SYSTEMMODAL, "", "You will need SciTE.exe to be running for ConsoleWrite to display.")
EndIf

Example()

Func Example()
    ; Register the function MyAdLibFunc() to be called every 250ms (default).
    AdlibRegister("MyAdLibFunc")

    ; Sleep does not stop AdLib functions from running.
    Sleep(1000)

    ; ==============================================================================================================================
    ; Help file : "AdLib functions don't run while a blocking function is shown e.g. MsgBox, InputBox, WinWait, WinWaitClose etc..."
    ; ==============================================================================================================================

    MsgBox($MB_SYSTEMMODAL, "", "No console message(s) will be shown whilst the messagebox is displayed.") ; ok, blocking function

    ; InputBox("Just a test", "Enter what you want") ; ok, blocking function

    ; Initiates a Browse for Folder dialog.
    ; $sFileSelectFolder = FileSelectFolder("Select a folder", "") ; ok, blocking function (help file, topic... HotKeySet)

    ; Initiates an Open File dialog.
    ; $sFileOpenDialog = FileOpenDialog("Select a file", @WindowsDir & "\", "All (*.*)") ; ok, blocking function

    ; Initiates a Save File dialog.
    ; $sFileSaveDialog = FileSaveDialog("Choose a filename", @WorkingDir, "Scripts (*.au3)") ; ok, blocking function

    ; WinWait("fghdfghj") ; NOT a blocking function (help file wrong, topics AdlibRegister & AdlibUnRegister)
    ; *******

    ; Open WordPad before this test, then run this script without closing WordPad immediately
    ; WinWaitClose("WordPad") ; NOT a blocking function (help file wrong, topics AdlibRegister & AdlibUnRegister)
    ; ************

    ; https://www.autoitscript.com/forum/topic/197449-_arraydisplay-and-msgbox-at-same-time/
    ; Local $aArray[5] = [0, 1, 2, 3, 4]
    ; _ArrayDisplay($aArray) ; NOT a blocking function as a Mod wrote "_ArrayDisplay is a blocking function" in the precedent link
    ; *************

    ; When needed, add functions here for testing if they are blocking functions or not

    ; The AdLib function MyAdLibFunc() will start again.
    Sleep(1000)

    ; Unregister the function MyAdLibFunc() from being called every 250ms.
    AdlibUnRegister("MyAdLibFunc")
EndFunc   ;==>Example

Func MyAdLibFunc()
    ; Assign a static variable to hold the number of times the function is called.
    Local Static $iCount = 0
    $iCount += 1

    ConsoleWrite("MyAdLibFunc called " & $iCount & " time(s)" & @CRLF)
EndFunc   ;==>MyAdLibFunc

 

Link to post
Share on other sites
2 hours ago, pixelsearch said:

Edit: the Adlib function could even be shorter in OP's case, something like this :

@pixelsearch I was wondering why AdlibUnRegister("MyAdLibFunc") is called twice.

Is there a reason, or could the first one be removed?

#include <Array.au3>

Local $aVar = [0,1,2,3,4,5,6,7,8,9]
Local $iTimeOut = 5 ; <=== 5s, change to your wish
Global $g_sTitle = "Close in " & $iTimeOut & "s"

AdlibRegister("MyAdLibFunc", $iTimeOut * 1000)
_ArrayDisplay($aVar, $g_sTitle)
AdlibUnRegister("MyAdLibFunc")

; ...script continuation here

Func MyAdLibFunc()
    AdlibUnRegister("MyAdLibFunc")
    WinClose($g_sTitle)
EndFunc   ;==>MyAdLibFunc

 

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to post
Share on other sites

add timer  :think: to __ArrayDisplay_Share to auto close

#include <GUIConstantsEx.au3>

Example()
Func Example()
    Local $hGUI = GUICreate("Example", 400, 400)
    Local $idOK = GUICtrlCreateButton("OK", 310, 370, 85, 25)
    GUISetState(@SW_SHOW, $hGUI)

    Local $iTimmer = TimerInit()    ;<<=== timer
    While 1
        If TimerDiff($iTimmer) > 3000 Then ExitLoop     ;<<=== check to auto close
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $idOK

            EndSwitch
        WEnd
        GUIDelete($hGUI)
EndFunc

 

Link to post
Share on other sites
13 hours ago, pixelsearch said:

I never considered ArrayDisplay as a blocking function.

HI
Could you please explain/elaborate ?
ArrayDisplay (__ArrayDisplay_Share) includes a gui with an infinite While loop, and no global var inside to interact with to allow an exit from this loop
Your code works (nicely indeed) using a WinClose, which is (sort of) a brute force way and not really a gentle & sweet exit/return from the func :)

Link to post
Share on other sites
44 minutes ago, mikell said:

Could you please explain/elaborate ?

Hey Soulful cat @mikell it's been a long time !

imho a "blocking function" is a function that stops AdlibRegister to be called while the function is active, no more, no less.

If you look at the help file example, topics AdlibRegister or AdlibUnRegister, you'll notice this important sentence written in the example :

; AdLib functions don't run while a blocking function is shown e.g. MsgBox, InputBox, WinWait, WinWaitClose etc.

My tests above (from 2019) show this sentence is not true, because WinWait and WinWaitClose keep on running AdLib functions, while MsgBox and InputBox stop AdLib from running. So who wrote this sentence in the example as it's half true, half false ?

It would have been a better idea to indicate somewhere a list of all the blocking functions (or in the topic of each blocking function). A non exhaustive list is : MsgBox , InputBox , FileSelectFolder [as indicated in topic... HotKeySet ! then tested in 2019] , FileOpenDialog , FileSaveDialog etc...

That's the reason why I consider _ArrayDisplay "not blocking" as you can run an Adlib function while ArrayDisplay is active... no more, no less :)

15 hours ago, Nine said:

I like your solution, but I have found that in some situations (when the function is truly blocking)...

Nine expressed this in a nice way because he indicated why he always chooses "the second-process approach, which will work all the time". He knows that _ArrayDisplay isn't a "truly blocking function" (compared to MsgBox for example) and "truly" is the word !
So instead of checking each time if a function is a "truly" blocking function or not, he prefers to always use the 2nd process approach, while I prefer the simpler AdLib approach... when possible :) 

Link to post
Share on other sites

Another reason why I prefer the second-process approach is that you can pass as many parameters as you need to without creating global variables.  The adlib approach forces the creation of many globals if you intend to vary the calls.  Since the best practices in programming is to reduce as much as possible the usage of global variables... :)

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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...