Jump to content
Sign in to follow this  
0Ethan0

How to achieve a responsive GUI while running a function with a loop?

Recommended Posts

0Ethan0

Ahoy Autoit Community!

After many trials and errors I am unable to solve a problem I am facing and would appreciate any kind of input or better yet a solution :)

The Premise: An embeded slideshow viewer that runs after double-clicking an item in a ListView (each item will generate a different slideshow images).

The Setup: GUI with a ListView Control and a simple exit button.

The Issue: Once double clicked the slide plays however the GUI "locks"/non responsive until the slide is over. Same thing if I click on the "Test" button.

The Culprit: I believe since it's in the images loop it can't accept any other commands until that loop is over.

The Wish: I want to be able to use the GUI functions (selecting other items, clicking on button etc.) while the slideshow plays.

The Code (stripped and simplified as much as I could):

#include <GuiListView.au3>
#include <File.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Opt("GUIOnEventMode", 1)

HotKeySet("{Esc}", "_Exit")

Global $c=0
Global $ssGDI[3], $ssGraphic[2], $ssImage
Global Const $bg_color = "000000"
Global Const $ssW = 480, $ssH = 320
Global $aFiles = _FileListToArrayRec("d:\testStage\", "*.jpg;*.png;*.bmp;*.gif;*.JPG;*.PNG;*.BMP;*.GIF", $FLTAR_FILES, $FLTAR_NORECUR ,$FLTAR_SORT ,$FLTAR_FULLPATH )


$guiW = 1200
$guiH = 726
$mainWindow = GUICreate("Slideshow Viewer", $guiW, $guiH, -1, -1, $WS_POPUP)
$Button1 = GUICtrlCreateButton("Exit", 0, 0, 50, 50)
GUICtrlSetOnEvent($Button1, "_Exit")
$Button1 = GUICtrlCreateButton("Test", 60, 0, 50, 50)
GUICtrlSetOnEvent($Button1, "Test")


Global $ListView = GUICtrlCreateListView("Entry Name|Category", 5, 75, 195, 280)
_GUICtrlListView_SetColumnWidth ($ListView, 0, 100)
_GUICtrlListView_SetColumnWidth ($ListView, 1, 100)
GUICtrlSendMsg($ListView, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_GRIDLINES, $LVS_EX_GRIDLINES)
GUICtrlSendMsg($ListView, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_FULLROWSELECT, $LVS_EX_FULLROWSELECT)
GUICtrlCreateListViewItem("Name 1|Category 1", $ListView)
GUICtrlCreateListViewItem("Name 2|Category 2", $ListView)

screenshotWidgetInit($ssW,$ssH, 690, 100)
GUISetState(@SW_SHOW, $mainWindow)

GUIRegisterMsg($WM_NOTIFY, "WM_Notify_Events")

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            _Exit()
    EndSwitch
WEnd

Func Test()
    For $k = 1 To UBound($aFiles) - 1
        screenshotWidgetTransition($aFiles[$k])
    Next
EndFunc

Func ListView_Click()
    ConsoleWrite("Left Click")
EndFunc

Func ListView_DoubleClick()
    ConsoleWrite("Double Left Click")
    Test()
EndFunc

Func WM_Notify_Events($hWndGUI, $MsgID, $wParam, $lParam)
    #forceref $hWndGUI, $MsgID, $wParam
    Local $tagNMHDR, $event, $hwndFrom, $code
    $tagNMHDR = DllStructCreate("int;int;int", $lParam)
    If @error Then Return
    $event = DllStructGetData($tagNMHDR, 3)
    Select
    Case $wParam = $ListView
        Select
            Case $event = $NM_CLICK
                ListView_Click ()
            Case $event = $NM_DBLCLK
                ListView_DoubleClick ()
            EndSelect
    EndSelect
    Return $GUI_RUNDEFMSG
EndFunc

Func screenshotWidgetTransition($image, $delay = 0, $speed = 1, $sleep = 2000)
    Local $a, $d = $c, $iX, $iY
    $ssImage = _GDIPlus_ImageLoadFromFile($image)
    $iX = _GDIPlus_ImageGetWidth($ssImage)
    $iY = _GDIPlus_ImageGetHeight($ssImage)

    $FDesktop=$ssH/$ssW
    $Fact =1
    If $iX > $ssW And $FDesktop > ($iY/$iX) Then
        $Fact=$ssW/$iX
    ElseIf $iY > $ssH Then
        $Fact=$ssH/$iY
    EndIf
    $H1 = Round(($Fact * $iY),0)
    $W1 = Round(($Fact * $iX),0)

    _GDIPlus_GraphicsDrawImageRect($ssGraphic[$d], $ssImage,($ssW - $W1)/2, ($ssH - $H1) / 2,$W1,$H1)

    WinSetTrans($ssGDI[$d], "", 0)
    WinSetOnTop($ssGDI[$d], "", 1)
    For $a = 0 To 254 Step $speed
        WinSetTrans($ssGDI[$d], "", $a)
        Sleep($delay)
    Next
    WinSetTrans($ssGDI[$d], "", 254)
    WinSetOnTop($ssGDI[Not ($d)], "", 0)
    WinSetTrans($ssGDI[Not ($d)], "", 0)
    _GDIPlus_GraphicsClear($ssGraphic[Not ($d)])
    $c = 1 - $d

    _GDIPlus_ImageDispose ($ssImage) ; very important to realease the pics
    Sleep($sleep)
EndFunc   ;==>screenshotWidgetTransition

Func screenshotWidgetInit($ssW,$ssH,$ssX,$ssY)
    $ssGDI[2] = GUICreate("", $ssW, $ssH, $ssX, $ssY, $WS_POPUP, $WS_EX_MDICHILD, $mainWindow)
    $ssGDI[0] = GUICreate("", $ssW, $ssH, 3, 3, $WS_POPUP, $WS_EX_MDICHILD, $ssGDI[2])
    $ssGDI[1] = GUICreate("", $ssW, $ssH, 3, 3, $WS_POPUP, $WS_EX_MDICHILD, $ssGDI[2])
;    GUISetBkColor("0x" & $bg_color, $ssGDI[2])
    GUISetState(@SW_SHOW, $ssGDI[2])
    GUISetState(@SW_SHOW, $ssGDI[0])
    GUISetState(@SW_SHOW, $ssGDI[1])
    WinSetTrans($ssGDI[0], "", 0)
    WinSetTrans($ssGDI[1], "", 0)
    _GDIPlus_Startup()
    $ssGraphic[0] = _GDIPlus_GraphicsCreateFromHWND($ssGDI[0])
    $ssGraphic[1] = _GDIPlus_GraphicsCreateFromHWND($ssGDI[1])
    _GDIPlus_GraphicsClear($ssGraphic[0], "0xFF" & $bg_color)
    _GDIPlus_GraphicsClear($ssGraphic[1], "0xFF" & $bg_color)
EndFunc   ;==>screenshotWidgetInit

Func _Exit()
    _GDIPlus_ImageDispose($ssImage)
    _GDIPlus_GraphicsDispose($ssGraphic[0])
    _GDIPlus_GraphicsDispose($ssGraphic[1])
    GUIDelete($ssGDI[0])
    GUIDelete($ssGDI[1])
    GUIDelete($ssGDI[2])
    _GDIPlus_Shutdown()
    Exit
EndFunc   ;==>_Exit

I hope someone can shed light on this; perhaps a different approach is needed?

Thank you in advance!

P.S.
The script is patched from different scripts of different users in the forum - thank you again users! :)

Edited by 0Ethan0

Share this post


Link to post
Share on other sites
nend

You have some blocking function in it like sleep.
Also Guioneventmode give some problem in your case.

I fixed it, see the code.

#include <GuiListView.au3>
#include <File.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

HotKeySet("{Esc}", "_Exit")

Global $c=0
Global $ssGDI[3], $ssGraphic[2], $ssImage
Global Const $bg_color = "000000"
Global Const $ssW = 480, $ssH = 320
Global $aFiles = _FileListToArrayRec("d:\testStage\", "*.jpg;*.png;*.bmp;*.gif;*.JPG;*.PNG;*.BMP;*.GIF", $FLTAR_FILES, $FLTAR_NORECUR ,$FLTAR_SORT ,$FLTAR_FULLPATH )


$guiW = 1200
$guiH = 726
$mainWindow = GUICreate("Slideshow Viewer", $guiW, $guiH, -1, -1, $WS_POPUP)
$Button1 = GUICtrlCreateButton("Exit", 0, 0, 50, 50)
$Button2 = GUICtrlCreateButton("Test", 60, 0, 50, 50)


Global $ListView = GUICtrlCreateListView("Entry Name|Category", 5, 75, 195, 280)
_GUICtrlListView_SetColumnWidth ($ListView, 0, 100)
_GUICtrlListView_SetColumnWidth ($ListView, 1, 100)
GUICtrlSendMsg($ListView, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_GRIDLINES, $LVS_EX_GRIDLINES)
GUICtrlSendMsg($ListView, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_FULLROWSELECT, $LVS_EX_FULLROWSELECT)
GUICtrlCreateListViewItem("Name 1|Category 1", $ListView)
GUICtrlCreateListViewItem("Name 2|Category 2", $ListView)

screenshotWidgetInit($ssW,$ssH, 690, 100)
GUISetState(@SW_SHOW, $mainWindow)

GUIRegisterMsg($WM_NOTIFY, "WM_Notify_Events")

While 1
   _Check_MSG()
WEnd

Func _Check_MSG()
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            _Exit()
        Case $Button1
            _Exit()
        Case $Button2
            Test()
    EndSwitch
EndFunc

Func Test()
    For $k = 1 To UBound($aFiles) - 1
        screenshotWidgetTransition($aFiles[$k])
    Next
EndFunc

Func ListView_Click()
    ConsoleWrite("Left Click")
EndFunc

Func ListView_DoubleClick()
    ConsoleWrite("Double Left Click")
    Test()
EndFunc

Func WM_Notify_Events($hWndGUI, $MsgID, $wParam, $lParam)
    #forceref $hWndGUI, $MsgID, $wParam
    Local $tagNMHDR, $event, $hwndFrom, $code
    $tagNMHDR = DllStructCreate("int;int;int", $lParam)
    If @error Then Return
    $event = DllStructGetData($tagNMHDR, 3)
    Select
    Case $wParam = $ListView
        Select
            Case $event = $NM_CLICK
                ListView_Click ()
            Case $event = $NM_DBLCLK
                ListView_DoubleClick ()
            EndSelect
    EndSelect
    Return $GUI_RUNDEFMSG
EndFunc

Func screenshotWidgetTransition($image, $delay = 0, $speed = 1, $sleep = 2000)
    Local $a, $d = $c, $iX, $iY
    $ssImage = _GDIPlus_ImageLoadFromFile($image)
    $iX = _GDIPlus_ImageGetWidth($ssImage)
    $iY = _GDIPlus_ImageGetHeight($ssImage)

    $FDesktop=$ssH/$ssW
    $Fact =1
    If $iX > $ssW And $FDesktop > ($iY/$iX) Then
        $Fact=$ssW/$iX
    ElseIf $iY > $ssH Then
        $Fact=$ssH/$iY
    EndIf
    $H1 = Round(($Fact * $iY),0)
    $W1 = Round(($Fact * $iX),0)

    _GDIPlus_GraphicsDrawImageRect($ssGraphic[$d], $ssImage,($ssW - $W1)/2, ($ssH - $H1) / 2,$W1,$H1)

    WinSetTrans($ssGDI[$d], "", 0)
    WinSetOnTop($ssGDI[$d], "", 1)
    For $a = 0 To 254 Step $speed
        WinSetTrans($ssGDI[$d], "", $a)
        _Check_MSG()
        Sleep($delay)
    Next
    WinSetTrans($ssGDI[$d], "", 254)
    WinSetOnTop($ssGDI[Not ($d)], "", 0)
    WinSetTrans($ssGDI[Not ($d)], "", 0)
    _GDIPlus_GraphicsClear($ssGraphic[Not ($d)])
    $c = 1 - $d

    _GDIPlus_ImageDispose ($ssImage) ; very important to realease the pics
    $timer = TimerInit()
    While TimerDiff($timer) < $sleep
        _Check_MSG()
    WEnd

EndFunc   ;==>screenshotWidgetTransition

Func screenshotWidgetInit($ssW,$ssH,$ssX,$ssY)
    $ssGDI[2] = GUICreate("", $ssW, $ssH, $ssX, $ssY, $WS_POPUP, $WS_EX_MDICHILD, $mainWindow)
    $ssGDI[0] = GUICreate("", $ssW, $ssH, 3, 3, $WS_POPUP, $WS_EX_MDICHILD, $ssGDI[2])
    $ssGDI[1] = GUICreate("", $ssW, $ssH, 3, 3, $WS_POPUP, $WS_EX_MDICHILD, $ssGDI[2])
;    GUISetBkColor("0x" & $bg_color, $ssGDI[2])
    GUISetState(@SW_SHOW, $ssGDI[2])
    GUISetState(@SW_SHOW, $ssGDI[0])
    GUISetState(@SW_SHOW, $ssGDI[1])
    WinSetTrans($ssGDI[0], "", 0)
    WinSetTrans($ssGDI[1], "", 0)
    _GDIPlus_Startup()
    $ssGraphic[0] = _GDIPlus_GraphicsCreateFromHWND($ssGDI[0])
    $ssGraphic[1] = _GDIPlus_GraphicsCreateFromHWND($ssGDI[1])
    _GDIPlus_GraphicsClear($ssGraphic[0], "0xFF" & $bg_color)
    _GDIPlus_GraphicsClear($ssGraphic[1], "0xFF" & $bg_color)
EndFunc   ;==>screenshotWidgetInit

Func _Exit()
    _GDIPlus_ImageDispose($ssImage)
    _GDIPlus_GraphicsDispose($ssGraphic[0])
    _GDIPlus_GraphicsDispose($ssGraphic[1])
    GUIDelete($ssGDI[0])
    GUIDelete($ssGDI[1])
    GUIDelete($ssGDI[2])
    _GDIPlus_Shutdown()
    Exit
EndFunc   ;==>_Exit

 

Edited by nend
  • Thanks 1

Share this post


Link to post
Share on other sites
0Ethan0

nend, Thank you so much for the reply and the code - it gave me a clearer concept of how things work behind the Autoit scene : )

I also read in the Wiki about the exact problem I was facing --> https://www.autoitscript.com/wiki/Interrupting_a_running_function

I hope it's OK to share the link here, just for others who stumble upon this topic can have a better understanding.

 

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  

  • Similar Content

    • guinness
      By guinness
      #include <Array.au3> #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> ; Proof of concept for using the control id as an index item for an array. I created back on 8th April 2013. Example() Func Example() ; Create the GUI. Local $iHeight = 400, $iWidth = 400 Local $hGUI = GUICreate('', $iWidth, $iHeight) GUISetState(@SW_SHOW, $hGUI) ; Declare variables to be used throughout the example. Local Const $BUTTON_ROWS_COLUMNS = 8 Local Enum $eCTRL_HWND, $eCTRL_VALUE, $eCTRL_MAX Local $aMsg[1][$eCTRL_MAX], _ $iButtonHeight = $iHeight / $BUTTON_ROWS_COLUMNS, _ $iButtonWidth = $iWidth / $BUTTON_ROWS_COLUMNS, _ $iControlID = 0 For $i = 0 To $BUTTON_ROWS_COLUMNS - 1 For $j = 0 To $BUTTON_ROWS_COLUMNS - 1 $iControlID = GUICtrlCreateButton($i & ',' & $j, $i * $iButtonWidth, $j * $iButtonHeight, $iButtonWidth, $iButtonHeight, $BS_CENTER) ; Increase the size of the array if the control id is greater than or equal to the total size of the array. If $iControlID >= UBound($aMsg) Then ReDim $aMsg[Ceiling($iControlID * 1.3)][$eCTRL_MAX] EndIf ; Add to the array. $aMsg[$iControlID][$eCTRL_HWND] = GUICtrlGetHandle($iControlID) $aMsg[$iControlID][$eCTRL_VALUE] = 'Sample string for the control id: ' & $iControlID Next Next ; Clear empty items after the last created control id. ReDim $aMsg[$iControlID + 1][$eCTRL_MAX] ; Display the array created. _ArrayDisplay($aMsg) Local $iMsg = 0 While 1 $iMsg = GUIGetMsg() Switch $iMsg Case $GUI_EVENT_CLOSE ExitLoop Case $aMsg[$eCTRL_HWND][$eCTRL_HWND] To UBound($aMsg) ; If $iMsg is greater than 0 and between the 0th index of $aMsg and the last item then display in the console. If $iMsg > 0 Then ConsoleWrite('Control Hwnd: ' & $aMsg[$iMsg][$eCTRL_HWND] & ', ' & $aMsg[$iMsg][$eCTRL_VALUE] & @CRLF) EndIf EndSwitch WEnd GUIDelete($hGUI) EndFunc ;==>Example  
    • XinYoung
      By XinYoung
      For fun, I'm building an app that opens a webpage and refreshes it every 30 seconds.
      But once the script performs _IEAction($oIE, "refresh"), the GUI closes.
      Any help is appreciated.
       

      #include <ButtonConstants.au3>
      #include <EditConstants.au3>
      #include <GUIConstantsEx.au3>
      #include <StaticConstants.au3>
      #include <WindowsConstants.au3>
      #include <WinAPIFiles.au3>
      #include <Array.au3>
      #include <File.au3>
      #include <Excel.au3>
      #include <DateTimeConstants.au3>
      #include <MsgBoxConstants.au3>
      #include <WinAPIShellEx.au3>
      #include <MsgBoxConstants.au3>
      #include <Date.au3>
      #include <ComboConstants.au3>
      #include <guimenu.au3>
      #include <IE.au3>
      HotKeySet("{F4}", "_Exit")
      ;Open the file(s) in the selected folder
      $extension = ".txt"
      $app2openWith = @SystemDir & "\notepad.exe"
      Func Begin()
          Global $loopTrick = 0
          #Region ### START Koda GUI section ### Form=c:\users\mchu\downloads\autoit\my code\form1.kxf
          Global $UI = GUICreate("Hit Em Up!", 256, 113, -1, -1)
          GUISetBkColor(0x000000)
          $menu = _GUICtrlMenu_GetSystemMenu($UI)
          _GUICtrlMenu_EnableMenuItem($menu, $SC_CLOSE, 1, False)
          Global $url = GUICtrlCreateInput("https://www.youtube.com/watch?v=dQw4w9WgXcQ", 81, 8, 160, 21)
          $Label1 = GUICtrlCreateLabel("Target:", 16, 8, 55, 17)
          GUICtrlSetFont(-1, 12, 800, 0, "MS Sans Serif")
          GUICtrlSetColor(-1, 0x00FF00)
          Global $StartBut = GUICtrlCreateButton("Start", 16, 40, 67, 25)
          GUICtrlSetFont(-1, 13, 800, 0, "MS Sans Serif")
          GUICtrlSetBkColor(-1, 0x008000)
          $Label2 = GUICtrlCreateLabel("(Press F4 to Exit)", 96, 40, 8000, 17)
          GUICtrlSetFont(-1, 12, 800, 0, "MS Sans Serif")
          GUICtrlSetColor(-1, 0x00FF00)
          GUISetState(@SW_SHOW)
          #EndRegion ### END Koda GUI section ###
          While 1
              $UIfunc = GUIGetMsg()
              Select
                  Case $UIfunc = $GUI_EVENT_CLOSE
                      _Exit()
                  Case $UIfunc = $StartBut
                      If GUICtrlRead($url) = "" Then
                          MsgBox(48, "Um...", "Give me a target you idiot.")
                      Else
                          GUICtrlSetState($url, $GUI_DISABLE)
                          GUICtrlSetState($StartBut, $GUI_DISABLE)
                          Start()
                      EndIf
              EndSelect
          WEnd
      EndFunc   ;==>Begin
      Func Start()
          If $loopTrick = 0 Then
              Global $oIE = _IECreate(GUICtrlRead($url))
              _IELoadWait($oIE)
              Again()
          ElseIf $loopTrick = 1 Then
              Sleep(3000)
              _IEAction($oIE, "refresh")
              Sleep(3000)
              Start()
          EndIf
      EndFunc   ;==>Start
      Func Again()
          $loopTrick = 1
          Start()
      EndFunc   ;==>Again
      Func _Exit()
          Exit
      EndFunc   ;==>_Exit
    • Skysnake
      By Skysnake
      I am tracking this topic by @LarsJ.  It is very advanced and overkill for what I am currently trying to do.
       
      Problem is this.
      Listview contains columns, one of which is right aligned and gets populated by float values, such as 123.99.  Some do not have decimals ie 124.00 and on sort gets truncated to 124.  Its obviously still the same value, but the display has reset.
      ; line below is for list VIEW ;..................................0.........1......2............ $cListView = GUICtrlCreateListView("CUSTOMER|AMOUNT|DESCRIPTION", 8, 152, 764, 279) GUICtrlSetBkColor($cListView, $GUI_BKCOLOR_LV_ALTERNATE) ; alternate between the listview background color and the listview item background color GUICtrlSetBkColor($cListView, $LVStdClr) ; Set the background color for the listview _GUICtrlListView_SetColumnWidth($cListView, 0, 120) ; -- the client name _GUICtrlListView_SetColumnWidth($cListView, 1, 90) ;-- the amount _GUICtrlListView_JustifyColumn($cListView, 1, 1) ; 1 - Text is right aligned _GUICtrlListView_SetColumnWidth($cListView, 2, 200) ; the description What I am looking for is something native and simple like a 
          _GUICtrlListView_SetColumnFormat($cListView, 1, "%.2f") ;  1 - column is stringformatted to "%.2f"
      So that after each sort it will appear as it was in the original rendering.
      Is there something like this? I have not been able to find a simple solution.

      Thanks.
      Skysnake
    • kcvinu
      By kcvinu
      Hi all,
      I have a button created with _GUICtrlButton_Create function. I know that this function returns a handle of button instead of an ID. So i have obtain control ID by calling _WinAPI_GetDlgCtrlID function. After that i have tried the GUICtrlSetBkColor function. But it didnt worked. Any suggestions will be appreciated. Thanks in advance. 
      Note : - The window which carries this button is not created with native gui create function. Instead, it is created with CreateWindowEx api function.
    • kcvinu
      By kcvinu
      Hi all,
      I am playing with _GUICtrlButton_Create function. How can i change this button's (or the entire form's) font ?. The in-built GUICtrlSetFont function is not working even when i convert the control handle to control ID with _WinAPI_GetDlgCtrlID ( ) function.  Do i need to use CreateFont api finction and send WM_SETFONT message ? Or is there any other easy and safe ways to do this ?. Thanks in advance.
      Note : This window is created by CreateWindowEx function, not by GUICreate function. 
×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.