Jump to content

[SOLVED] WM_COMMAND to cancel a download


JoeBar
 Share

Recommended Posts

Hi, i have a program which download files from a server with InetGet.

Here's the GUI : gui.jpg.3998fc2ca4e69b7d198fb175cd4500a6.jpg

Télécharger means Download

Quitter means Quit

Here's the modified code for comprehension :

Opt("GUIOnEventMode", 1)
Opt("TrayIconHide", 1)
GUISetOnEvent($GUI_EVENT_CLOSE, _Exit)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_SYSCOMMAND, "_WM_SYSCOMMAND")

GUISetState(@SW_SHOW, $DltGui)

Global $returnvalue2 = 0

Func _DL()
    Global $returnvalue = 0
    If $returnvalue2 = 1 Then
        $returnvalue2 = 0
        Return
    EndIf
    Local $snomfichierdl = _ArrayToString(StringRegExp($aCSV[GUICtrlRead($tab) * 4 + 3], "\/([\w\-\.]+)$", 1))
    Global $sSaveFile = FileSaveDialog("Enregistrer le fichier", @DesktopDir, "Tous (*.*)", 16, $snomfichierdl)
    If @error Then Return
    
    GUICtrlSetData(Eval("btndl" & GUICtrlRead($tab) * 4), "Cancel")
    GUICtrlSetTip(Eval("btndl" & GUICtrlRead($tab) * 4), "Cancel the DL")
    GUICtrlSetOnEvent(Eval("btndl" & GUICtrlRead($tab) * 4), _CancelDL)
    
    Global $hInetget = InetGet($urlfilauth, $sSaveFile, 1, 1)
    Local $Bytes, $NewBytes, $pourcent_New
    $size = InetGetSize($urlfilauth)
    Local $nowRead = 0
    Local $pourcent = 0
    GUICtrlSetState($dlspeed, $GUI_SHOW)
    Do
        If $returnvalue = 1 Then
            $returnvalue = 0
            $returnvalue2 = 1
            Return
        EndIf
        $Bytes = Round(InetGetInfo($hInetget, 0))
        Sleep(1000)
        $NewBytes = Round(InetGetInfo($hInetget, 0))
        GUICtrlSetData($dlspeed, _String_GetFormattedSize($NewBytes - $Bytes, 2, -1) & "/s")
        $nowRead = InetGetInfo($hInetget, 0)
        $pourcent = Int(($nowRead / $size) * 100)
        GUICtrlSetData($hprogress, $pourcent)
    Until InetGetInfo($hInetget, 2) ; Check if the download is complete.
    InetClose($hInetget)
    GUICtrlSetState(Eval("btnopen" & GUICtrlRead($tab) * 4), $GUI_ENABLE)
    _RetabControls()
EndFunc   ;==>_DL

Func _RetabControls()
    GUICtrlSetState($dlspeed, $GUI_HIDE)
    GUICtrlSetData(Eval("btndl" & GUICtrlRead($tab) * 4), "Download")
    GUICtrlSetTip(Eval("btndl" & GUICtrlRead($tab) * 4), "Download the File")
    GUICtrlSetOnEvent(Eval("btndl" & GUICtrlRead($tab) * 4), _DL)
    GUICtrlSetData($hprogress, 0)
EndFunc   ;==>_RetabControls

Func _WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
    If $wParam = 0xF060 And InetGetInfo() <> 0 Then
        _InterruptionDL()
    EndIf
    Return 'GUI_RUNDEFMSG'
EndFunc   ;==>_WM_SYSCOMMAND

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    #forceref $hWnd, $Msg, $lParam
    If _WinAPI_LoWord($wParam) = Eval("btndl" & GUICtrlRead($tab) * 4) And _WinAPI_HiWord($wParam) = $BN_CLICKED And InetGetInfo() <> 0 Then
        _CancelDL()
    EndIf
    If _WinAPI_HiWord($wParam) = $GUI_EVENT_CLOSE Or _WinAPI_LoWord($wParam) = $Quitter And InetGetInfo() <> 0 Then
        _InterruptionDL()
    EndIf
    Return 'GUI_RUNDEFMSG'
EndFunc   ;==>WM_COMMAND

Func _InterruptionDL()
    If MsgBox(36, "Confirmation", "Cancel the DL and Quit ?") = 6 Then
        FileDelete($sSaveFile)
        GUIDelete($DltGui)
        Exit
    EndIf
EndFunc   ;==>_InterruptionDL

Func _CancelDL()
    If MsgBox(36, "Confirmation", "Cancel the DL ?") = 6 Then
        InetClose($hInetget)
        FileDelete($sSaveFile)
        $returnvalue = 1
        _RetabControls()
    EndIf
EndFunc   ;==>_CancelDL

Func _Launch()
    If FileExists($sSaveFile) Then
        ShellExecute($sSaveFile)
    Else
        MsgBox($MB_ICONERROR, "Error", "File does not exist")
    EndIf
EndFunc   ;==>_Launch

Func _String_GetFormattedSize($iByteSize, $iRound = 2, $sRetFormat = -1)
    Local $asBytes[9] = [8, 'Ko', 'Mo', 'Go', 'To', 'Po', 'Eo', 'Zo', 'Yo'] ;Last two unreachable ;)
    Local $iBytes_Val = 2 ^ 10
    If $iByteSize < $iBytes_Val Then Return $iByteSize & ' Octets'
    Local $iRetFormat_IsString = IsString($sRetFormat)
    Local $iFor = 1, $iTo = 8, $iStep = 1
    If $iRetFormat_IsString Then
        If Not StringRegExp($sRetFormat, "\A(?i)(Ko|Mo|Go|To|Po|Eo|Zo|Yo)\z") Then Return SetError(1, 0, $iByteSize)
    Else
        Local $iFor = 8, $iTo = 1, $iStep = -1
    EndIf
    For $i = $iFor To $iTo Step $iStep
        If ($iRetFormat_IsString And $sRetFormat = $asBytes[$i]) Or _
                (Not $iRetFormat_IsString And $iByteSize >= $iBytes_Val ^ $i) Then
            Return Round($iByteSize / $iBytes_Val ^ $i, $iRound) & ' ' & $asBytes[$i]
        EndIf
    Next
EndFunc   ;==>_String_GetFormattedSize

Func _Exit()
    GUIDelete($DltGui)
    Exit
EndFunc   ;==>_Exit

While 1
    Sleep(100) ;Idle
WEnd

I stripped useless functions as my problem is somewhat targeted.

So the user press "Télécharger" to "Download" the file, the button is changed in "Cancel" and the download begins.

All is working fine until here. I had to add a message handler to be able to cancel the download or quit while it's downloading.

Once the user push "Cancel", i pop a MsgBox to confirm cancelling. If the user say yes, it stops InetGet, delete the file, set the former button back, and try to get out of the DL loop by setting a flag $returnvalue to "True". That was the only way i had to get out of the _DL func. Is there another way ?

I put the second $returnvalue2 at the beginning of _DL because when i get out of the loop and the func, it reenters in _DL for a reason i don't understand.

So when the user Cancel the download, it reopens the FileDialog instead of getting out of the _DL func and waiting.

Is there a way to avoid the use of $returnvalue and have a clean behaviour of the program ?

Edited by JoeBar
Code translation for better understanding
Link to comment
Share on other sites

Here's a working code that you can run to check ;)

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ButtonConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIConv.au3>

Opt("GUIOnEventMode", 1)
GUISetOnEvent($GUI_EVENT_CLOSE, _Exit)
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_SYSCOMMAND, "_WM_SYSCOMMAND")
;~ Global $returnvalue = 0
;~ Global $returnvalue2 = 0

Global $DltGui = GUICreate("Test DL", 600, 315, -1, -1, -1, -1)
Global $Quit = GUICtrlCreateButton("Quit", 445, 20, 133, 50, -1, -1)
GUICtrlSetOnEvent(-1, _Exit)
GUICtrlSetFont(-1, 15, 400, 0, "MS Reference Sans Serif")
Global $dlspeed = GUICtrlCreateLabel("", 276, 291, 94, 18, $SS_RIGHT, -1)
GUICtrlSetFont(-1, 8, 700, 0, "MS Sans Serif")
GUICtrlSetColor(-1, "0x0000FF")
GUICtrlSetBkColor(-1, "-2")
Global $hprogress = GUICtrlCreateProgress(380, 289, 198, 20, -1, -1)
Global $IdButtonDL = GUICtrlCreateButton("Download", 443, 166, 133, 37, -1, -1)
GUICtrlSetFont(-1, 14, 400, 0, "MS Reference Sans Serif")
GUICtrlSetOnEvent(-1, _DL)
Global $IdButtonOpen = GUICtrlCreateButton("Open File", 443, 231, 133, 37, -1, -1)
GUICtrlSetFont(-1, 12, 400, 0, "MS Reference Sans Serif")
GUICtrlSetOnEvent(-1, _Launch)
GUICtrlSetState(-1, $GUI_DISABLE)
GUISetState(@SW_SHOW, $DltGui)

Func _DL()
;~      $returnvalue = 0
;~  If $returnvalue2 = 1 Then
;~      $returnvalue2 = 0
;~      Return
;~  EndIf
    Local $snomfichierdl = "10Gio.dat"
    Global $sSaveFile = FileSaveDialog("Enregistrer le fichier", @DesktopDir, "Tous (*.*)", 16, $snomfichierdl)
    If @error Then Return
    GUICtrlSetData($IdButtonDL, "Annuler")
    GUICtrlSetTip($IdButtonDL, "Annuler le téléchargement")
    GUICtrlSetOnEvent($IdButtonDL, _CancelDL)
    $urlfile = "http://www.ovh.net/files/10Gio.dat"
    Global $hInetget = InetGet($urlfile, $sSaveFile, 1, 1)
    Local $Bytes, $NewBytes, $pourcent_New
    $size = InetGetSize($urlfile)
    Local $nowRead = 0
    Local $pourcent = 0
    GUICtrlSetState($dlspeed, $GUI_SHOW)
    Do
;~      If $returnvalue = 1 Then
;~          $returnvalue = 0
;~          $returnvalue2 = 1
;~          Return
;~      EndIf
        $Bytes = Round(InetGetInfo($hInetget, 0))
        Sleep(1000)
        $NewBytes = Round(InetGetInfo($hInetget, 0))
        GUICtrlSetData($dlspeed, _String_GetFormattedSize($NewBytes - $Bytes, 2, -1) & "/s")
        $nowRead = InetGetInfo($hInetget, 0)
        $pourcent = Int(($nowRead / $size) * 100)
        GUICtrlSetData($hprogress, $pourcent)
    Until InetGetInfo($hInetget, 2) ; Check if the download is complete.
    InetClose($hInetget)
    GUICtrlSetState($IdButtonOpen, $GUI_ENABLE)
    _RetabControls()
EndFunc   ;==>_DL

Func _RetabControls()
    GUICtrlSetState($dlspeed, $GUI_HIDE)
    GUICtrlSetData($IdButtonDL, "Download")
    GUICtrlSetOnEvent($IdButtonDL, _DL)
    GUICtrlSetData($hprogress, 0)
EndFunc   ;==>_RetabControls

Func _WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
    If $wParam = 0xF060 And InetGetInfo() <> 0 Then
        _InterruptionDL()
    EndIf
    Return 'GUI_RUNDEFMSG'
EndFunc   ;==>_WM_SYSCOMMAND

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    #forceref $hWnd, $Msg, $lParam
    If _WinAPI_LoWord($wParam) = $IdButtonDL And _WinAPI_HiWord($wParam) = $BN_CLICKED And InetGetInfo() <> 0 Then
        _CancelDL()
    EndIf
    If _WinAPI_HiWord($wParam) = $GUI_EVENT_CLOSE Or _WinAPI_LoWord($wParam) = $Quit And InetGetInfo() <> 0 Then
        _InterruptionDL()
    EndIf
    Return 'GUI_RUNDEFMSG'
EndFunc   ;==>WM_COMMAND

Func _InterruptionDL()
    If MsgBox(36, "Confirmation", "Cancel the DL and quit ?") = 6 Then
        FileDelete($sSaveFile)
        GUIDelete($DltGui)
        Exit
    EndIf
EndFunc   ;==>_InterruptionDL

Func _CancelDL()
    If MsgBox(36, "Confirmation", "Cancel the DL ?") = 6 Then
        InetClose($hInetget)
        FileDelete($sSaveFile)
        $returnvalue = 1
        _RetabControls()
    EndIf
EndFunc   ;==>_CancelDL

Func _Launch()
    If FileExists($sSaveFile) Then
        ShellExecute($sSaveFile)
    Else
        MsgBox($MB_ICONERROR, "Error", "File not found !")
    EndIf
EndFunc   ;==>_Launch

Func _String_GetFormattedSize($iByteSize, $iRound = 2, $sRetFormat = -1)
    Local $asBytes[9] = [8, 'Ko', 'Mo', 'Go', 'To', 'Po', 'Eo', 'Zo', 'Yo'] ;Last two unreachable ;)
    Local $iBytes_Val = 2 ^ 10
    If $iByteSize < $iBytes_Val Then Return $iByteSize & ' Octets'
    Local $iRetFormat_IsString = IsString($sRetFormat)
    Local $iFor = 1, $iTo = 8, $iStep = 1
    If $iRetFormat_IsString Then
        If Not StringRegExp($sRetFormat, "\A(?i)(Ko|Mo|Go|To|Po|Eo|Zo|Yo)\z") Then Return SetError(1, 0, $iByteSize)
    Else
        Local $iFor = 8, $iTo = 1, $iStep = -1
    EndIf
    For $i = $iFor To $iTo Step $iStep
        If ($iRetFormat_IsString And $sRetFormat = $asBytes[$i]) Or _
                (Not $iRetFormat_IsString And $iByteSize >= $iBytes_Val ^ $i) Then
            Return Round($iByteSize / $iBytes_Val ^ $i, $iRound) & ' ' & $asBytes[$i]
        EndIf
    Next
EndFunc   ;==>_String_GetFormattedSize

Func _Exit()
    GUIDelete($DltGui)
    Exit
EndFunc   ;==>_Exit

While 1
    Sleep(100) ;Idle
WEnd

The behaviour is the same 🙄

Link to comment
Share on other sites

GUICtrlSetOnEvent takes the name of the function as a string :) (Wrap them in quotes)

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

@seadoggie01 both forms are accepted (with or without quotes).

@JoeBar Here streamlined :

#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>
#include <InetConstants.au3>

Global $bDownLoading = False, $bCanceling = False, $sSaveFile, $hInetget

Opt("GUIOnEventMode", 1)

Global $DltGui = GUICreate("Test DL", 600, 315, -1, -1, -1, -1)
Global $Quit = GUICtrlCreateButton("Quit", 445, 20, 133, 50, -1, -1)
GUICtrlSetOnEvent(-1, _Exit)
GUICtrlSetFont(-1, 15, 400, 0, "MS Reference Sans Serif")
Global $dlspeed = GUICtrlCreateLabel("", 276, 291, 94, 18, $SS_RIGHT, -1)
GUICtrlSetFont(-1, 8, 700, 0, "MS Sans Serif")
GUICtrlSetColor(-1, "0x0000FF")
GUICtrlSetBkColor(-1, "-2")
Global $hprogress = GUICtrlCreateProgress(380, 289, 198, 20, -1, -1)
Global $IdButtonDL = GUICtrlCreateButton("Download", 443, 166, 133, 37, -1, -1)
GUICtrlSetFont(-1, 14, 400, 0, "MS Reference Sans Serif")
GUICtrlSetOnEvent(-1, _DL_Handler)
Global $IdButtonOpen = GUICtrlCreateButton("Open File", 443, 231, 133, 37, -1, -1)
GUICtrlSetFont(-1, 12, 400, 0, "MS Reference Sans Serif")
GUICtrlSetOnEvent(-1, _Launch)
GUICtrlSetState(-1, $GUI_DISABLE)
GUISetState(@SW_SHOW, $DltGui)
GUISetOnEvent($GUI_EVENT_CLOSE, _Exit)

Local $aInet

While 1
  Sleep(500)
  If $bDownLoading Then
    $aInet = InetGetInfo($hInetget)
    If $aInet[2] Or $bCanceling Then
      InetClose($hInetget)
      $bDownLoading = False
      If $bCanceling Then
        FileDelete($sSaveFile)
        $bCanceling = False
      Else
        GUICtrlSetState($IdButtonOpen, $GUI_ENABLE)
      EndIf
      GUICtrlSetData($IdButtonDL, "Download")
      GUICtrlSetData($hprogress, 0)
    Else
      GUICtrlSetData($hprogress, Int($aInet[0] / $aInet[1] * 100))
    EndIf
  EndIf
WEnd

Func _DL_Handler()
  If $bDownLoading Then
    Local $iRep = MsgBox($MB_YESNO, "Confirmation", "Stop Download ?")
    If $iRep = $IDYES Then $bCanceling = True
  Else
    $sSaveFile = FileSaveDialog("Enregistrer le fichier", @DesktopDir, "Tous (*.*)", 16, "10Mio.dat")
    If @error Then Return
    $bDownLoading = True
    _StartDL()
  EndIf
EndFunc   ;==>_DL_Handler

Func _StartDL()
  GUICtrlSetData($IdButtonDL, "Cancel")
  Local $urlfile = "http://www.ovh.net/files/10Mio.dat"
  $hInetget = InetGet($urlfile, $sSaveFile, $INET_FORCERELOAD, $INET_DOWNLOADBACKGROUND)
EndFunc   ;==>_StartDL

Func _Launch()
  If FileExists($sSaveFile) Then
    ShellExecute($sSaveFile)
  Else
    MsgBox($MB_ICONERROR, "Error", "File not found !")
  EndIf
EndFunc   ;==>_Launch

Func _Exit()
  GUIDelete($DltGui)
  Exit
EndFunc   ;==>_Exit

ps. I removed the fancy stuff and there's still Inet Errors to check...

Link to comment
Share on other sites

Hi, thank you !

So, just your loop can get rid of all the Messages interceptions system.

Well i just overthought it another time 🤓

I just modified the _Exit func to fit my example :

Func _Exit()
    If $bDownLoading Then
        Local $iRep = MsgBox($MB_YESNO, "Confirmation", "Annuler le téléchargement et quitter ?")
        If $iRep = $IDYES Then
            InetClose($hInetget)
            FileDelete($sSaveFile)
            Exit
        EndIf
    Else
        Exit
    EndIf
EndFunc   ;==>_Exit

Thank you @Nine  :thumbsup:

Edit : I successfully use your script with some modifications to make it working, it's perfect now 👍

Edited by JoeBar
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...