click here for a plain text version
;.......script written by trancexx (trancexx at yahoo dot com)

#include-once

#INDEX# ========================================================================================
; Title ...............: GIFAnimation v2.1.2
; File Name............: GIFAnimation.au3
; Min. AutoIt Version..: v3.3.2.0
; Description .........: Display GIF in AutoIt
; Author... ...........: trancexx
; Dll .................: kernel32.dll, user32.dll, gdi32.dll, comctl32.dll, ole32.dll, gdiplus.dll
; ================================================================================================

;if not $GDI_dll then $GDI_dll = "gdiplus.dll"

#CONSTANTS# ===============================================================================

; Pseudo-handles for DLLs to use
Global Const $hGIFDLL__KERNEL32 = DllOpen("kernel32.dll")
Global Const $hGIFDLL__USER32 = DllOpen("user32.dll")
Global Const $hGIFDLL__GDI32 = DllOpen("gdi32.dll")
Global Const $hGIFDLL__COMCTL32 = DllOpen("comctl32.dll")
Global Const $hGIFDLL__OLE32 = DllOpen("ole32.dll")
;Global Const $hGIFDLL__GDIPLUS = DllOpen($GDI_dll)
Global Const $hGIFDLL__GDIPLUS = DllOpen("gdiplus.dll")

;============================================================================================
#GLOBAL# ==================================================================================
; GIF associative string. Don't try to edit the content, this is very important internal variable!
Global $sGIF__ASSOCSTRING_INTERNAL = ";"
;============================================================================================

#CURRENT# =================================================================================
;_GIF_DeleteGIF
;_GIF_ExitAnimation
;_GIF_GetCurrentFrame
;_GIF_GetDimension
;_GIF_GetSize
;_GIF_PauseAnimation
;_GIF_RefreshGIF
;_GIF_ResumeAnimation
;_GIF_ValidateGIF
;_GUICtrlCreateGIF
;_GUICtrlSetGIF
; ===========================================================================================

#FUNCTION# ;===============================================================================
; Name...........: _GIF_DeleteGIF
; Description ...: Deletes GIF control
; Syntax.........: _GIF_DeleteGIF($iGIFId)
; Parameters ....: $iGIFId - Control ID. Returned by _GUICtrlCreateGIF function
; Return values .: Returns 1
; Author ........: trancexx
;============================================================================================
Func _GIF_DeleteGIF($iGIFId$fDelCtrl = True)
    Local $pGIF = _GIF_GetGIFAssoc($iGIFId)
    ; Read $pGIF (shorter version - only handles and memory pointers)
    Local $tGIF = DllStructCreate("handle GIFThread;" & _
            "ptr CodeBuffer;" & _
            "hwnd ControlHandle;" & _
            "handle ImageList;" & _
            "bool ExitFlag;", _
            $pGIF)
    ; GIFThread. Will alow it to exit gracefully for it to close all internally opened handles
    Local $hGIFThread = DllStructGetData($tGIF"GIFThread")
    If $hGIFThread Then
        ; Maybe it's suspended
        _GIF_ResumeThread($hGIFThread)
        ; Set exit Flag
        DllStructSetData($tGIF"ExitFlag", 1)
        ; Thread will exit now. Wait for it to exit
        _GIF_WaitForSingleObject($hGIFThread)
        _GIF_CloseHandle($hGIFThread; closing the handle
    EndIf
    ; CodeBuffer
    Local $pCodeBuffer = DllStructGetData($tGIF"CodeBuffer")
    If $pCodeBuffer Then _GIF_MemGlobalFree($pCodeBuffer)
    ; ImageList
    Local $hImageList = DllStructGetData($tGIF"ImageList")
    If $hImageList Then _GIF_ImageList_Destroy($hImageList)
    ; The rest of the cleaning job
    _GIF_MemGlobalFree($pGIF)
    ; Not sure if GUICtrlDelete will delete associated Bitmap. Will do that by myself...
    _GIF_DeleteObject(GUICtrlSendMsg($iGIFId, 370, 0, 0)) ; STM_SETIMAGE
    ; Delete control
    If $fDelCtrl Then GUICtrlDelete($iGIFId)
    ; Remove this entry from global assoc string
    $sGIF__ASSOCSTRING_INTERNAL = StringReplace($sGIF__ASSOCSTRING_INTERNAL$iGIFId & "|" & $pGIF & ";""")
    Return 1
EndFunc   ;==>_GIF_DeleteGIF

#FUNCTION# ;===============================================================================
; Name...........: _GIF_ExitAnimation
; Description ...: Exits animation of GIF control
; Syntax.........: _GIF_ExitAnimation($iGIFId)
; Parameters ....: $iGIFId - Control ID. Returned by _GUICtrlCreateGIF function
; Return values .: Returns 1
; Author ........: trancexx
;============================================================================================
Func _GIF_ExitAnimation($iGIFId)
    Local $pGIF = _GIF_GetGIFAssoc($iGIFId)
    ; Read $pGIF (shorter version - only handles and memory pointers)
    Local $tGIF = DllStructCreate("handle GIFThread;" & _
            "ptr CodeBuffer;" & _
            "hwnd ControlHandle;" & _
            "handle ImageList;" & _
            "bool ExitFlag;" & _
            "bool Transparent;" & _
            "dword CurrentFrame;", _
            $pGIF)
    ; GIFThread. Will alow it to exit gracefully for it to close all internally opened handles
    Local $hGIFThread = DllStructGetData($tGIF"GIFThread")
    If $hGIFThread Then
        ; Maybe it's suspended
        _GIF_ResumeThread($hGIFThread)
        ; Set exit Flag
        DllStructSetData($tGIF"ExitFlag", 1)
        ; Thread will exit now. Wait for it to exit
        _GIF_WaitForSingleObject($hGIFThread)
        _GIF_CloseHandle($hGIFThread; closing the handle
        DllStructSetData($tGIF"GIFThread", 0)
    EndIf
    ; CodeBuffer
    Local $pCodeBuffer = DllStructGetData($tGIF"CodeBuffer")
    If $pCodeBuffer Then _GIF_MemGlobalFree($pCodeBuffer)
    DllStructSetData($tGIF"CodeBuffer", 0)
    ; ImageList
    Local $hImageList = DllStructGetData($tGIF"ImageList")
    If $hImageList Then _GIF_ImageList_Destroy($hImageList)
    DllStructSetData($tGIF"ImageList", 0)
    ; Set value of CurrentFrame to 0
    DllStructSetData($tGIF"CurrentFrame", 0)
    ; Refresh the control
    GUICtrlSetState($iGIFId, GUICtrlGetState($iGIFId))
    Return 1
EndFunc   ;==>_GIF_ExitAnimation

#FUNCTION# ;===============================================================================
; Name...........: _GIF_GetCurrentFrame
; Description ...: Retrieves index of currently displayed frame of the GIF control
; Syntax.........: _GIF_GetCurrentFrame($iGIFId)
; Parameters ....: $iGIFId - Control ID. Returned by _GUICtrlCreateGIF function
; Return values .: Returns frame index
; Author ........: trancexx
;============================================================================================
Func _GIF_GetCurrentFrame($iGIFId)
    Local $pGIF = _GIF_GetGIFAssoc($iGIFId)
    ; Read $pGIF (shorter version)
    Local $tGIF = DllStructCreate("handle GIFThread;" & _
            "ptr CodeBuffer;" & _
            "hwnd ControlHandle;" & _
            "handle ImageList;" & _
            "bool ExitFlag;" & _
            "bool Transparent;" & _
            "dword CurrentFrame;", _
            $pGIF)
    Return DllStructGetData($tGIF"CurrentFrame")
EndFunc   ;==>_GIF_GetCurrentFrame

#FUNCTION# ;===============================================================================
; Name...........: _GIF_GetDimension
; Description ...: Returns array of GIF image dimension
; Syntax.........: _GIF_GetDimension($vGIF [, $vAdditionalData])
; Parameters ....: $vGIF - filename of the GIF file
;                  $vAdditionalData - optional parameter used if the GIF if embedded resource inside PE file.
;                                     resurce type, name and language (all separated by semicolon ';')
;                                     language is optional
; Return values .: Success - Returns array which first element [0] is width,
;                                                second element [1] is height
;                  Failure - Returns array which first element [0] is 0 (zero),
;                                                second element [1] is 0 (zero),
;                          - Sets @error:
;                           |1 - invalid input or Gdip failure
; Author ........: trancexx
;============================================================================================
Func _GIF_GetDimension($vGIF$vAdditionalData = "")
    Local $aOut[2] = [0, 0] ; preset output
    Local $vData
    ; Process passed
    If IsBinary($vGIF) Then ; GIF binary data passed
        $vData = $vGIF
    Else
        If $vAdditionalData Then ; likely resource
            Local $aData = StringSplit($vAdditionalData";", 2)
            If UBound($aData) < 3 Then ReDim $aData[3]
            $vData = _GIF_ResourceGetAsRaw($vGIF$aData[0], $aData[1], $aData[2])
            If @error Then
                $vData = $vGIF ; it's not resource, $vAdditionalData was wrong
            Else
                ; RT_BITMAP is stored without BMP header. Add it:
                If $aData[0] = 2 Then $vData = _GIF_MakeBitmapFromRT_BITMAP($vData)
            EndIf
        Else
            $vData = $vGIF ; maybe $vGIF is the file name
        EndIf
    EndIf
    Local $hGDIP ; Gdip engine
    Local $hMemGlobal ; Memory
    ; Bitmap object
    Local $pBitmap$iWidth$iHeight
    If IsString($vData) Then
        $pBitmap = _GIF_CreateBitmapFromFile($hGDIP$vData$iWidth$iHeight)
        If @error Then $pBitmap = _GIF_CreateBitmapFromBinaryImage($hGDIP$hMemGlobal, Binary($vData), $iWidth$iHeight)
        If @error Then
            $vData = FileRead($vData)
            $pBitmap = _GIF_CreateBitmapFromBinaryImage($hGDIP$hMemGlobal$vData$iWidth$iHeight)
        EndIf
    Else
        $pBitmap = _GIF_CreateBitmapFromBinaryImage($hGDIP$hMemGlobal$vData$iWidth$iHeight)
    EndIf
    If @error Then Return SetError(1, 0, $aOut; Nothing worked. Invalid input or Gdip failure.
    _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal)
    $aOut[0] = $iWidth
    $aOut[1] = $iHeight
    Return $aOut
EndFunc   ;==>_GIF_GetDimension

#FUNCTION# ;===============================================================================
; Name...........: _GIF_GetSize
; Description ...: Returns array of GIF Control dimension
; Syntax.........: _GIF_GetSize($iGIFId)
; Parameters ....: $iGIFId - Control ID. Returned by _GUICtrlCreateGIF function
; Return values .: Success - Returns array which first element [0] is width,
;                                                second element [1] is height,
;                  Failure - Returns array which first element [0] is 0 (zero),
;                                                second element [1] is 0 (zero),
;                           Sets @error to 1
; Author ........: trancexx
;============================================================================================
Func _GIF_GetSize($iGIFId)
    Local $pGIF = _GIF_GetGIFAssoc($iGIFId)
    Local $aOut[2] = [0, 0] ; preset output
    ; Read $pGIF (shorter version)
    Local $tGIF = DllStructCreate("handle GIFThread;" & _
            "ptr CodeBuffer;" & _
            "hwnd ControlHandle;" & _
            "handle ImageList;", _
            $pGIF)
    ; ImageList
    Local $hImageList = DllStructGetData($tGIF"ImageList")
    If $hImageList Then Return _GIF_ImageList_GetIconSize($hImageList)
    Local $hControl = DllStructGetData($tGIF"ControlHandle")
    If Not $hControl Then Return SetError(1, 0, $aOut)
    Local $aArray = WinGetPos($hControl)
    If @error Then Return SetError(1, 0, $aOut)
    $aOut[0] = $aArray[2]
    $aOut[1] = $aArray[3]
    Return $aOut
EndFunc   ;==>_GIF_GetSize

#FUNCTION# ;===============================================================================
; Name...........: _GIF_PauseAnimation
; Description ...: Pauses animation of GIF control
; Syntax.........: _GIF_PauseAnimation($iGIFId)
; Parameters ....: $iGIFId - Control ID. Returned by _GUICtrlCreateGIF function
; Return values .: Returns 1
; Author ........: trancexx
;============================================================================================
Func _GIF_PauseAnimation($iGIFId)
    Local $pGIF = _GIF_GetGIFAssoc($iGIFId)
    ; Read $pGIF (short version - only GIFThread)
    Local $tGIF = DllStructCreate("handle GIFThread;"$pGIF)
    ; GIFThread
    Local $hGIFThread = DllStructGetData($tGIF"GIFThread")
    If Not $hGIFThread Then Return SetExtended(1, 1)
    If _GIF_SuspendThread($hGIFThread) Then _GIF_ResumeThread($hGIFThread; make sure not to increment suspended count of the thread
    Return 1
EndFunc   ;==>_GIF_PauseAnimation

#FUNCTION# ;===============================================================================
; Name...........: _GIF_RefreshGIF
; Description ...: Refreshes GIF control
; Syntax.........: _GIF_RefreshGIF($iGIFId)
; Parameters ....: $iGIFId - Control ID. Returned by _GUICtrlCreateGIF function
; Return values .: Success - Returns 1. Refreshes GIF control
;                  Failure - Sets @error:
;                  |1 - GIF Control doesn't exist
;                  |2 - Couldn't get DC for the control
; Remarks........: Meant to be used with GUIRegisterMsg function
; Author ........: trancexx
;============================================================================================
Func _GIF_RefreshGIF($iGIFId)
    Local $pGIF = _GIF_GetGIFAssoc($iGIFId)
    ; Make structure at $pGIF address
    Local $tGIF = DllStructCreate("handle GIFThread;" & _
            "ptr CodeBuffer;" & _
            "hwnd ControlHandle;" & _
            "handle ImageList;" & _
            "bool ExitFlag;" & _
            "bool Transparent;" & _
            "dword CurrentFrame;", _
            $pGIF)
    ; If there is no $pGIF error will occur. Great opportunity to return
    If @error Then Return SetError(1, 0, 0)
    ; Is it animated at all
    If Not DllStructGetData($tGIF"ImageList") Then Return 1
    ; Get DC
    Local $hDC = _GIF_GetDC(DllStructGetData($tGIF"ControlHandle"))
    If @error Then Return SetError(2, 0, 0)
    Local $iColorRef = -1
    If DllStructGetData($tGIF"Transparent") Then $iColorRef = _GIF_GetUnderlyingColor(DllStructGetData($tGIF"ControlHandle")) ; if transparent gif then set bk color to GUI's bk color
    _GIF_ImageList_DrawEx(DllStructGetData($tGIF"ImageList"), DllStructGetData($tGIF"CurrentFrame"), $hDC, 0, 0, 0, 0, $iColorRef, -1, 0)
    _GIF_ReleaseDC(0, $hDC)
    Return 1
EndFunc   ;==>_GIF_RefreshGIF

#FUNCTION# ;===============================================================================
; Name...........: _GIF_ResumeAnimation
; Description ...: Resumes stopped animation of GIF control
; Syntax.........: _GIF_ResumeAnimation($iGIFId)
; Parameters ....: $iGIFId - Control ID. Returned by _GUICtrlCreateGIF function
; Return values .: Returns 1
; Author ........: trancexx
;============================================================================================
Func _GIF_ResumeAnimation($iGIFId)
    Local $pGIF = _GIF_GetGIFAssoc($iGIFId)
    ; Read $pGIF (short version - only GIFThread)
    Local $tGIF = DllStructCreate("handle GIFThread;"$pGIF)
    ; GIFThread
    Local $hGIFThread = DllStructGetData($tGIF"GIFThread")
    If Not $hGIFThread Then Return SetExtended(1, 1)
    If _GIF_ResumeThread($hGIFThread) = 2 Then _GIF_SuspendThread($hGIFThread; make sure not to increment non-suspended count of the thread
    Return 1
EndFunc   ;==>_GIF_ResumeAnimation

#FUNCTION# ;===============================================================================
; Name...........: _GIF_ValidateGIF
; Description ...: Removes the GIF Control from the update region of the main window and in the same time upates the control
; Syntax.........: _GIF_ValidateGIF($iGIFId)
; Parameters ....: $iGIFId - Control ID. Returned by _GUICtrlCreateGIF function
; Return values .: Success - Returns 1
;                  Failure - Sets @error to 1
; Remarks........: Meant to be used with GUIRegisterMsg function
; Author ........: trancexx
;============================================================================================
Func _GIF_ValidateGIF($iGIFId)
    Local $pGIF = _GIF_GetGIFAssoc($iGIFId)
    ; Make structure at $pGIF address
    Local $tGIF = DllStructCreate("handle GIFThread;" & _
            "ptr CodeBuffer;" & _
            "hwnd ControlHandle;" & _
            "handle ImageList;" & _
            "bool ExitFlag;" & _
            "bool Transparent;" & _
            "dword CurrentFrame;" & _
            "dword NumberOfFrames;", _
            $pGIF)
    ; If there is no $pGIF error will occur. Great opportunity to return
    If @error Then Return SetError(1, 0, 0)
    ; Check to see if it's needed to proceed. If not then just return sucess
    If DllStructGetData($tGIF"NumberOfFrames") < 2 Then Return 1
    ; Is it animated at all
    If Not DllStructGetData($tGIF"GIFThread") Then Return 1
    ; Redraw the control
    _GIF_RedrawWindow(DllStructGetData($tGIF"ControlHandle"), 0, 0, 1280) ; RDW_UPDATENOW | RDW_FRAME
    _GIF_RefreshGIF($iGIFId)
    Return 1
EndFunc   ;==>_GIF_ValidateGIF

#FUNCTION# ;===============================================================================
; Name...........: _GUICtrlCreateGIF
; Description ...: Creates GIF control for the GUI
; Syntax.........: _GUICtrlCreateGIF($vGIF$vAdditionalData$iLeft$iTop [, $iWidth = Default [, $iHeight = Default [, $iRenderingStyle = Default [, $iForcedARGB = Default ]]]])
; Parameters ....: $vGIF - filename of the GIF to be loaded
;                  $vAdditionalData - resurce type, name and language (all separated by semicolon ';') if the GIF is stored as resource inside PE file
;                                     language is optional
;                  $iLeft - left side coordinate of the control
;                  $iTop - the top of the control
;                  $iWidth - [optional] the width of the control. Default is the width of the image.
;                  $iHeight - [optional] the height of the control. Default is the height of the image.
;                  $iRenderingStyle - [optional] Advanced optional parameter. Coresponds to style paremeter of ImageList_DrawEx function.Default is ILD_NORMAL for images with defined transparency.
;                  $iForcedARGB - [optional] Advanced optional parameter. Use with semi-transparent images. Default is 0xFF000000 (opaque black).
; Return values .: Success - Returns controlID of the new control
;                          - Sets @extended to 1 if GIF contains only one frame (no animation)
;                  Failure - Sets @error:
;                  |1 - if @extended is not set then failure is likely due to invalid input
;                       if @extended = 1 then Gdip failure occured
;                       0 (zero) is returned in both cases
;                  |2 - Needed memory allocation failed. Returns ControlID.
;                  |3 - Memory protection step failed. Returns ControlID.
;                  |4 - Some of the functions are not accessible for unknown reasons. Check @extended to determine which one. Returns ControlID.
;                  |5 - Couldn't create thread for the animation. Returns ControlID.
; Author ........: trancexx
;============================================================================================
Func _GUICtrlCreateGIF($vGIF$vAdditionalData$iLeft$iTop$iWidth = Default, $iHeight = Default, $iRenderingStyle = Default, $iForcedARGB = Default, $hGIFControl = 0)
    If $iWidth = -1 Then $iWidth = Default
    If $iHeight = -1 Then $iHeight = Default
    Local $vData
    ; Process passed
    If IsBinary($vGIF) Then ; GIF binary data passed
        $vData = $vGIF
    Else
        If $vAdditionalData Then ; likely resource
            Local $aData = StringSplit($vAdditionalData";", 2)
            If UBound($aData) < 3 Then ReDim $aData[3]
            $vData = _GIF_ResourceGetAsRaw($vGIF$aData[0], $aData[1], $aData[2])
            If @error Then
                $vData = $vGIF ; it's not resource, $vAdditionalData was wrong
            Else
                ; RT_BITMAP is stored without BMP header. Add it:
                If $aData[0] = 2 Then $vData = _GIF_MakeBitmapFromRT_BITMAP($vData)
            EndIf
        Else
            $vData = $vGIF ; maybe $vGIF is the file name
        EndIf
    EndIf
    ; Generate pGIF
    Local $iWidthDef$iHeightDef
    If Not IsKeyword($iWidthDef) = 1 Then $iWidthDef = $iWidth
    If Not IsKeyword($iHeightDef) = 1 Then $iHeightDef = $iHeight
    Local $pGIF = _GIF_Create_pGIF($vData$iWidthDef$iHeightDef$hGIFControl$iLeft$iTop$iForcedARGB)
    If @error Then ; try some more options
        $vData = FileRead($vData)
        $pGIF = _GIF_Create_pGIF($vData$iWidthDef$iHeightDef$hGIFControl$iLeft$iTop$iForcedARGB)
        If @error Then ; finally maybe it's GIF content passed as string
            $pGIF = _GIF_Create_pGIF(Binary($vGIF), $iWidthDef$iHeightDef$hGIFControl$iLeft$iTop$iForcedARGB)
            If @error Then Return SetError(1, @extended = True, 0) ; Nothing worked, Invalid input or Gdip failure.
        EndIf
    EndIf
    ; Arrange/parse that space
    Local $tGIF = DllStructCreate("handle GIFThread;" & _
            "ptr CodeBuffer;" & _
            "hwnd ControlHandle;" & _
            "handle ImageList;" & _
            "bool ExitFlag;" & _
            "bool Transparent;" & _
            "dword CurrentFrame;" & _
            "dword NumberOfFrames;", _
            $pGIF)
    ; Read NumberOfFrames to know the size of the structure
    Local $iFrameCount = DllStructGetData($tGIF"NumberOfFrames")
    ; Make it complete now:
    $tGIF = DllStructCreate("handle GIFThread;" & _
            "ptr CodeBuffer;" & _
            "hwnd ControlHandle;" & _
            "handle ImageList;" & _
            "bool ExitFlag;" & _
            "bool Transparent;" & _
            "dword CurrentFrame;" & _
            "dword NumberOfFrames;" & _
            "dword FrameDelay[" & $iFrameCount & "];", _
            $pGIF)
    ; Set default resizing value for this control
    GUICtrlSetResizing($hGIFControl, 802)
    ; Save Control handle
    DllStructSetData($tGIF"ControlHandle", GUICtrlGetHandle($hGIFControl))
    ; If there is just one frame there is no animation. Return control id
    If $iFrameCount = 1 Then
        ; Expand global assoc string
        $sGIF__ASSOCSTRING_INTERNAL &= $hGIFControl & "|" & $pGIF & ";"
        Return SetExtended(1, $hGIFControl)
    EndIf
    ; Allocate enough memory space for machine code
    Local $iSizeCodeBuffer = 157
    If @AutoItX64 Then $iSizeCodeBuffer = 220 ; x64 code is little longer
    Local $pCodeBuffer = _GIF_MemGlobalAlloc($iSizeCodeBuffer, 64) ; GPTR
    If @error Then Return SetError(2, 0, $hGIFControl; Couldn't allocate
    ; Save that value
    DllStructSetData($tGIF"CodeBuffer"$pCodeBuffer)
    ; Set proper 'protection'
    _GIF_VirtualProtect($pCodeBuffer$iSizeCodeBuffer, 64) ; MEM_EXECUTE_READWRITE
    If @error Then Return SetError(3, 0, $hGIFControl; Couldn't set MEM_EXECUTE_READWRITE
    Local $tCodeBuffer = DllStructCreate("byte[" & $iSizeCodeBuffer & "]"$pCodeBuffer)
    ; Get functions addresses
    Local $pImageList_DrawEx = _GIF_GetAddress(_GIF_GetModuleHandle("comctl32.dll"), "ImageList_DrawEx")
    If @error Then Return SetError(4, 1, $hGIFControl; Couldn't get address of ImageList_DrawEx function
    Local $pSleep = _GIF_GetAddress(_GIF_GetModuleHandle("kernel32.dll"), "Sleep")
    If @error Then Return SetError(4, 2, $hGIFControl; Couldn't get address of Sleep function
    Local $pGetPixel = _GIF_GetAddress(_GIF_GetModuleHandle("gdi32.dll"), "GetPixel")
    If @error Then Return SetError(4, 3, $hGIFControl; Couldn't get address of GetPixel function
    Local $hUser32 = _GIF_GetModuleHandle("user32.dll")
    Local $pGetDC = _GIF_GetAddress($hUser32"GetDC")
    If @error Then Return SetError(4, 4, $hGIFControl; Couldn't get address of GetDC function
    Local $pReleaseDC = _GIF_GetAddress($hUser32"ReleaseDC")
    If @error Then Return SetError(4, 5, $hGIFControl; Couldn't get address of ReleaseDC function
    ; Read from $tGIF
    Local $hImageList = DllStructGetData($tGIF"ImageList")
    Local $hControl = DllStructGetData($tGIF"ControlHandle")
    ; Define style for ImageList_DrawEx function
    Local $iStyle
    If $iRenderingStyle = Default Then
        $iStyle = 1
        If DllStructGetData($tGIF"Transparent") Then $iStyle = 0 ; correct value if needed
    Else
        $iStyle = $iRenderingStyle
    EndIf
    ; Write code
    If @AutoItX64 Then
        DllStructSetData($tCodeBuffer, 1, _
                "0x" & _
                "4883EC" & _GIF_SwapEndian(88, 1) & _                                    ; sub rsp, 88d ;<- expand the stack
                "" & _ ; 10 START
                "4831F6" & _                                                             ; xor rsi, rsi ;<- rsi = 0
                "" & _ ; 20 MAIN LOOP
                "" & _ ; 25 SET CurrentFrame
                "8BC6" & _                                                               ; mov aax, asi ;<- esi is current frame index. Copy it to eax
                "A3" & _GIF_SwapEndian(DllStructGetPtr($tGIF"CurrentFrame"), 8) & _    ; mov $pCurrentFrame, eax ;<- from eax to structure
                "" & _ ; 30 GET CONTROL'S DC
                "48B9" & _GIF_SwapEndian($hControl, 8) & _                               ; mov rcx,  Control handle
                "48B8" & _GIF_SwapEndian($pGetDC, 8) & _                                 ; mov rax, GetDC ;<- set rax to address of GetDC function
                "FFD0" & _                                                               ; call rax ;<- calling rax (function)
                "" & _ ; 50 SAVE DC (to release later)
                "4889C3" & _                                                             ; mov rbx, rax ;<- storing DC into rbx
                "" & _ ; 60 GET BACKGROUND COLOR (upper left pixel)
                "49C7C0" & _GIF_SwapEndian(0, 4) & _                                     ; mov r8, $iTop ;<- Y coordinate (0)
                "BA" & _GIF_SwapEndian(0, 4) & _                                         ; mov rdx, $iTop ;<- X coordinate (0)
                "4889C1" & _                                                             ; mov rcx, rax ;<- DC handle (currently rax=rbx, so I could have set it to rbx too with no difference)
                "48B8" & _GIF_SwapEndian($pGetPixel, 8) & _                              ; mov rax, GetPixel ;<- set rax to address of GetPixel function
                "FFD0" & _                                                               ; call rax ;<- calling rax (function)
                "" & _ ; 65 CHECK for CLR_INVALID
                "3D" & _GIF_SwapEndian(-1, 4) & _                                        ; cmp eax, -1
                "75" & _GIF_SwapEndian(2, 1) & _                                         ; jne 2d ;<- if not equal then jump forward 2 bytes; (to 70)
                "8BC7" & _                                                               ; mov eax, edi ; If CLR_INVALID then retrieve the color value from memory (edi register).
                "" & _ ; 70
                "8BF8" & _                                                               ; mov edi, eax ;<- from eax to edi This is to save the last valid value.
                "" & _ ; 80
                "89442438" & _                                                           ; mov [rsp+56], eax ;<- SET $iBkColRef parameter
                "B8" & _GIF_SwapEndian($iStyle, 4) & _                                   ; mov eax, $iStyle
                "89442448" & _                                                           ; mov [rsp+72], eax ;<- SET $iStyle parameter
                "4989D8" & _                                                             ; mov r8, rbx ; <- SET $hDC parameter
                "49C7C1" & _GIF_SwapEndian(0, 4) & _                                     ; mov r9, 0 ; <- SET $iXPos parameter
                "89F2" & _                                                               ; mov edx, esi ; <- SET $iImageIndex parameter
                "48B9" & _GIF_SwapEndian($hImageList, 8) & _                             ; mov rcx,  $hImageList handle ; <- SET $hImageList parameter
                "" & _ ; 100 DRAW FINALLY
                "48B8" & _GIF_SwapEndian($pImageList_DrawEx, 8) & _                      ; mov rax, $pImageList_DrawEx ;<- set rax to address of ImageList_DrawEx function
                "FFD0" & _                                                               ; call rax ;<- calling rax (function)
                "" & _ ; 110 RELEASE DC
                "4889DA" & _                                                             ; mov rdx, rbx ;<- previously stored DC
                "48B9" & _GIF_SwapEndian($hControl, 8) & _                               ; mov rcx, Control handle ;<- can be NULL too
                "48B8" & _GIF_SwapEndian($pReleaseDC, 8) & _                             ; mov rax, ReleaseDC ;<- set rax to address of ReleaseDC function
                "FFD0" & _                                                               ; call rax ;<- calling rax (function)
                "" & _ ; 115 CHECK IF EXIT FLAG IS SET
                "A1" & _GIF_SwapEndian(DllStructGetPtr($tGIF"ExitFlag"), 8) & _        ; mov eax, Address of ExitFlag
                "85C0" & _                                                               ; test eax, eax
                "75" & _GIF_SwapEndian(46, 1) & _                                        ; jne 46d ;<- if set then jump forward 46 bytes; (to 160)
                "" & _ ; 120 SLEEP FOR GIF TIME DELAY VALUE
                "48BB" & _GIF_SwapEndian(DllStructGetPtr($tGIF"FrameDelay"), 8) & _    ; mov rbx, Address of FrameDelay
                "488B0CB3" & _                                                           ; mov rcx, qword[rbx+4*rsi] ;<- move pointer for every new frame to exact position
                "48B8" & _GIF_SwapEndian($pSleep, 8) & _                                 ; mov rax, Sleep ;<- set rax to address of Sleep function
                "FFD0" & _                                                               ; call rax ;<- calling rax (function)
                "" & _ ; 130 INCREMENTATING 'POSITION INDEX'
                "FFC6" & _                                                               ; inc esi ;<- increment esi by value of 1
                "" & _ ; 140 CHECK 'POSITION'
                "81FE" & _GIF_SwapEndian($iFrameCount, 4) & _                            ; cmp esi, $iFrameCount ;<- compare esi with $iFrameCount
                "" & _ ; 150 DEAL WITH DIFFERENT CASES
                "74" & _GIF_SwapEndian(5, 1) & _                                         ; je 5d ;<- if equal jump forward five bytes
                "E9" & _GIF_SwapEndian(-200, 4) & _                                      ; jmp -200d ;<- jump back 200 bytes (to 20)
                "E9" & _GIF_SwapEndian(-208, 4) & _                                      ; jmp -208d ;<- jump back 208 bytes (to 10)
                "" & _ ; 160 SET EXIT CODE TO 0 BEFORE THE END
                "4831C0" & _                                                             ; xor rax, rax ;<- rax = 0
                "4883C4" & _GIF_SwapEndian(88, 1) & _                                    ; add rsp, 88d ;<- shrink stack (88 bytes)
                "C3" _                                                                   ; ret ;<- Return.
                )
    Else
        DllStructSetData($tCodeBuffer, 1, _
                "0x" & _
                "" & _ ; 10 START
                "33F6" & _                                                               ; xor esi, esi ;<- esi = 0
                "" & _ ; 20 MAIN LOOP
                "" & _ ; 25 SET CurrentFrame
                "8BC6" & _                                                               ; mov eax, esi ;<- esi is current frame index. Copy it to eax
                "A3" & _GIF_SwapEndian(DllStructGetPtr($tGIF"CurrentFrame"), 4) & _    ; mov $pCurrentFrame, eax ;<- from eax to structure
                "68" & _GIF_SwapEndian($iStyle, 4) & _                                   ; push Style
                "68" & _GIF_SwapEndian(-1, 4) & _                                        ; push FgColRef
                "" & _ ; GET CONTROL'S DC
                "68" & _GIF_SwapEndian($hControl, 4) & _                                 ; push Control handle
                "B8" & _GIF_SwapEndian($pGetDC, 4) & _                                   ; mov eax, GetDC ;<- set eax to address of GetDC function
                "FFD0" & _                                                               ; call eax ;<- calling eax (function)
                "" & _ ; 50 SAVE DC (to release later)
                "8BD8" & _                                                               ; mov ebx, eax ;<- storing DC into ebx
                "" & _ ; 60 GET BACKGROUND COLOR (upper left pixel)
                "68" & _GIF_SwapEndian(0, 4) & _                                         ; push Y coordinate
                "68" & _GIF_SwapEndian(0, 4) & _                                         ; push X coordinate
                "53" & _                                                                 ; push ebx ;<- DC handle (currently eax=ebx, so I could have pushed eax too with no difference)
                "B8" & _GIF_SwapEndian($pGetPixel, 4) & _                                ; mov eax, GetPixel ;<- set eax to address of GetPixel function
                "FFD0" & _                                                               ; call eax ;<- calling eax (function)
                "" & _ ; 65 CHECK for CLR_INVALID
                "3D" & _GIF_SwapEndian(-1, 4) & _                                        ; cmp eax, -1
                "75" & _GIF_SwapEndian(2, 1) & _                                         ; jne 2d ;<- if not equal then jump forward 2 bytes; (to 70)
                "8BC7" & _                                                               ; mov eax, edi ; If CLR_INVALID then retrieve the color value from memory (edi register).
                "" & _ ; 70
                "8BF8" & _                                                               ; mov edi, eax ;<- from eax to edi This is to save the last valid value.
                "" & _ ; 80
                "50" & _                                                                 ; push eax ; push retrieved background color on the stack
                "68" & _GIF_SwapEndian(0, 4) & _                                         ; push Height
                "68" & _GIF_SwapEndian(0, 4) & _                                         ; push Width
                "68" & _GIF_SwapEndian(0, 4) & _                                         ; push YPos
                "68" & _GIF_SwapEndian(0, 4) & _                                         ; push XPos
                "53" & _                                                                 ; push ebx ;<- push DC (again)
                "56" & _                                                                 ; push esi ;<- this is ImageList's index of the frame to render
                "68" & _GIF_SwapEndian($hImageList, 4) & _                               ; push ImageList
                "" & _ ; 100 DRAW FINALLY
                "B8" & _GIF_SwapEndian($pImageList_DrawEx, 4) & _                        ; mov eax, ImageList_DrawEx ;<- set eax to address of ImageList_DrawEx function
                "FFD0" & _                                                               ; call eax ;<- calling eax (function)
                "" & _ ; 110 RELEASE DC
                "53" & _                                                                 ; push ebx ;<- DC is found in ebx
                "68" & _GIF_SwapEndian($hControl, 4) & _                                 ; push Control handle ;<- can be NULL also
                "B8" & _GIF_SwapEndian($pReleaseDC, 4) & _                               ; mov eax, ReleaseDC ;<- set eax to address of ReleaseDC function
                "FFD0" & _                                                               ; call eax ;<- calling eax (function)
                "" & _ ; 115 CHECK IF EXIT FLAG IS SET
                "A1" & _GIF_SwapEndian(DllStructGetPtr($tGIF"ExitFlag"), 4) & _        ; mov eax, Address of ExitFlag
                "85C0" & _                                                               ; test eax, eax
                "75" & _GIF_SwapEndian(35, 1) & _                                        ; jne 35d ;<- if set then jump forward 35 bytes; (to 160)
                "" & _ ; 120 SLEEP FOR GIF TIME DELAY VALUE
                "BB" & _GIF_SwapEndian(DllStructGetPtr($tGIF"FrameDelay"), 4) & _      ; mov ebx, Address of FrameDelay
                "8B0CB3" & _                                                             ; mov ecx, dword[ebx+4*esi] ;<- move pointer for every new frame to exact position
                "51" & _                                                                 ; push ecx ;<- push TimeDelay value
                "B8" & _GIF_SwapEndian($pSleep, 4) & _                                   ; mov eax, Sleep ;<- set eax to address of Sleep function
                "FFD0" & _                                                               ; call eax ;<- calling eax (function)
                "" & _ ; 130 INCREMENTATING 'POSITION INDEX'
                "46" & _                                                                 ; inc esi ;<- increment esi by value of 1
                "" & _ ; 140 CHECK 'POSITION'
                "81FE" & _GIF_SwapEndian($iFrameCount, 4) & _                            ; cmp esi, $iFrameCount ;<- compare esi with $iFrameCount
                "" & _ ; 150 DEAL WITH DIFFERENT CASES
                "74" & _GIF_SwapEndian(5, 1) & _                                         ; je 5d ;<- if equal jump forward five bytes
                "E9" & _GIF_SwapEndian(-147, 4) & _                                      ; jmp -147d ;<- jump back 147 bytes (to 20)
                "E9" & _GIF_SwapEndian(-154, 4) & _                                      ; jmp -154d ;<- jump back 154 bytes (to 10)
                "" & _ ; 160 SET EXIT CODE TO 0 BEFORE THE END
                "33C0" & _                                                               ; xor eax, eax ;<- eax = 0
                "C3" _                                                                   ; ret ;<- Return.
                )
            EndIf
    ; Create thread in which to run the code
    Local $hThread = _GIF_CreateThread($pCodeBuffer)
    If @error Then Return SetError(5, 0, $hGIFControl; Couldn't create thread
    ; Save that handle
    DllStructSetData($tGIF"GIFThread"$hThread)
    ; Redraw parent window
    _GIF_InvalidateRect(_GIF_GetParent($hControl))
    ; Expand global assoc string
    $sGIF__ASSOCSTRING_INTERNAL &= $hGIFControl & "|" & $pGIF & ";"
    ; All went well. Return Control Identifier
    Return $hGIFControl
EndFunc   ;==>_GUICtrlCreateGIF

#FUNCTION# ;===============================================================================
; Name...........: _GUICtrlSetGIF
; Description ...: Sets the image for a control
; Syntax.........: _GUICtrlSetGIF($iControld$vGIF, [$vAdditionalData = Default, [, $iRenderingStyle = Default [, $iForcedARGB = Default]]])
; Parameters ....: $iControld - The control identifier (controlID)
;                  $vGIF - filename of the GIF to be loaded
;                  $vAdditionalData - resurce type, name and language (all separated by semicolon ';') if the GIF is stored as resource inside PE file
;                                     language is optional. Default is empty string (no additional data).
;                  $iRenderingStyle - [optional] Advanced optional parameter. Coresponds to style paremeter of ImageList_DrawEx function.Default is ILD_NORMAL for images with defined transparency.
;                  $iForcedARGB - [optional] Advanced optional parameter. Use with semi-transparent images. Default is 0xFF000000 (opaque black).
; Return values .: Success - Returns True.
;                          - Sets @extended to 1 if GIF contains only one frame (no animation)
;                  Failure - Returns False.
;                          - Sets @error:
;                  |1 - if @extended is not set then failure is likely due to invalid input
;                       if @extended = 1 then Gdip failure occured.
;                  |2 - Needed memory allocation failed.
;                  |3 - Memory protection step failed.
;                  |4 - Some of the functions are not accessible for unknown reasons. Check @extended to determine which one.
;                  |5 - Couldn't create thread for the animation.
;                  |6 - Control ID invalid.
; Author ........: trancexx
;============================================================================================
Func _GUICtrlSetGIF($iControld$vGIF$vAdditionalData = Default, $iRenderingStyle = Default, $iForcedARGB = Default)
    Local $aCtrlPos = WinGetPos(GUICtrlGetHandle($iControld))
    If @error Then Return SetError(6, 0, False)
    If $vAdditionalData = Default Then $vAdditionalData = ""
    If $aCtrlPos[2] = 0 Then $aCtrlPos[2] = Default
    If $aCtrlPos[3] = 0 Then $aCtrlPos[3] = Default
    _GIF_DeleteGIF($iControld, False)
    _GUICtrlCreateGIF($vGIF$vAdditionalData$aCtrlPos[0], $aCtrlPos[1], $aCtrlPos[2], $aCtrlPos[3], $iRenderingStyle$iForcedARGB$iControld)
    Return SetError(@error, @extended, Not @error)
EndFunc   ;==>_GUICtrlSetGIF

#INTERNAL FUNCTIONS DOWN BELOW# ;==========================================================
Func _GIF_CloseHandle($hHandle)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"bool""CloseHandle""handle"$hHandle)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_CloseHandle

Func _GIF_WaitForSingleObject($hHandle$iMiliSec = -1)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"dword""WaitForSingleObject""handle"$hHandle"dword"$iMiliSec)
    If @error Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_WaitForSingleObject

Func _GIF_CreateThread($pAddress)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"handle""CreateThread", _
            "ptr", 0, _
            "dword_ptr", 0, _
            "ptr"$pAddress, _
            "ptr", 0, _
            "dword", 0, _
            "dword*", 0)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_CreateThread

Func _GIF_SuspendThread($hTread)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"dword""SuspendThread""handle"$hTread)
    If @error Or $aCall[0] = -1 Then Return SetError(1, 0, -1)
    Return $aCall[0]
EndFunc   ;==>_GIF_SuspendThread

Func _GIF_ResumeThread($hTread)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"dword""ResumeThread""handle"$hTread)
    If @error Or $aCall[0] = -1 Then Return SetError(1, 0, -1)
    Return $aCall[0]
EndFunc   ;==>_GIF_ResumeThread

Func _GIF_VirtualProtect($pAddress$iSize$iProtection)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"bool""VirtualProtect""ptr"$pAddress"dword_ptr"$iSize"dword"$iProtection"dword*", 0)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_VirtualProtect

Func _GIF_GetAddress($hModule$vFuncName)
    Local $sType = "str"
    If IsNumber($vFuncName) Then $sType = "int" ; if ordinal value passed
    Local $aCall = DllCall($hGIFDLL__KERNEL32"ptr""GetProcAddress""handle"$hModule$sType$vFuncName)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_GetAddress

Func _GIF_GetModuleHandle($vModule = 0)
    Local $sType = "wstr"
    If Not $vModule Then $sType = "ptr"
    Local $aCall = DllCall($hGIFDLL__KERNEL32"ptr""GetModuleHandleW"$sType$vModule)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_GetModuleHandle

Func _GIF_GetBkColor($hWnd)
    Local $hDC = _GIF_GetDC($hWnd)
    If @error Then Return SetError(1, 0, -1)
    Local $aCall = DllCall($hGIFDLL__GDI32"dword""GetBkColor""handle"$hDC)
    If @error Or $aCall[0] = -1 Then
        _GIF_ReleaseDC($hWnd$hDC)
        Return SetError(2, 0, -1)
    EndIf
    _GIF_ReleaseDC($hWnd$hDC)
    Return $aCall[0]
EndFunc   ;==>_GIF_GetBkColor

Func _GIF_GetDC($hWnd)
    Local $aCall = DllCall($hGIFDLL__USER32"handle""GetDC""hwnd"$hWnd)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_GetDC

Func _GIF_ReleaseDC($hWnd$hDC)
    Local $aCall = DllCall($hGIFDLL__USER32"int""ReleaseDC""hwnd"$hWnd"handle"$hDC)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_ReleaseDC

Func _GIF_InvalidateRect($hWnd$pRect = 0, $fErase = True)
    Local $aCall = DllCall($hGIFDLL__USER32"bool""InvalidateRect", _
            "hwnd"$hWnd, _
            "ptr"$pRect, _
            "bool"$fErase)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_InvalidateRect

Func _GIF_ValidateRect($hWnd$pRect = 0)
    Local $aCall = DllCall($hGIFDLL__USER32"bool""ValidateRect""hwnd"$hWnd"ptr"$pRect)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_ValidateRect

Func _GIF_RedrawWindow($hWnd$pRect$hRegion$iFlags)
    Local $aCall = DllCall($hGIFDLL__USER32"bool""RedrawWindow""hwnd"$hWnd"ptr"$pRect"handle"$hRegion"dword"$iFlags)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_RedrawWindow

Func _GIF_GetUnderlyingColor($hWnd)
    Local $hParent = _GIF_GetParent($hWnd)
    If @error Then Return SetError(1, 0, -1)
    Local $iColor = _GIF_GetBkColor($hParent)
    Return SetError(@error, 0, $iColor)
EndFunc   ;==>_GIF_GetUnderlyingColor

Func _GIF_GetParent($hWnd)
    Local $aCall = DllCall($hGIFDLL__USER32"hwnd""GetParent""hwnd"$hWnd)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_GetParent

Func _GIF_Create_pGIF($bBinary, ByRef $iWidth, ByRef $iHeight, ByRef $hGIFControl$iLeft = 0, $iTop = 0, $iARGB = Default)
    If $iARGB = Default Then $iARGB = 0xFF000000
    Local $hGDIP ; Gdip engine
    Local $hMemGlobal ; Memory
    ; Bitmap object
    Local $pBitmap$iWidthReal$iHeightReal
    If IsBinary($bBinary) Then
        $pBitmap = _GIF_CreateBitmapFromBinaryImage($hGDIP$hMemGlobal$bBinary$iWidthReal$iHeightReal)
    Else
        $pBitmap = _GIF_CreateBitmapFromFile($hGDIP$bBinary$iWidthReal$iHeightReal)
    EndIf
    If @error Then
        Local $iErr = @error
        _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal)
        Return SetError(1, $iErr, 0)
    EndIf
    Local $fDoResize
    If $iWidth = Default Then
        $iWidth = $iWidthReal
    Else
        $fDoResize = True
    EndIf
    If $iHeight = Default Then
        $iHeight = $iHeightReal
    Else
        $fDoResize = True
    EndIf
    ; Get number of frame dimensions
    Local $iFrameDimensionsCount = _GIF_GdipImageGetFrameDimensionsCount($pBitmap)
    If @error Then
        _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal)
        Return SetError(2, 0, 0)
    EndIf
    ; GUID
    Local $tGUID = DllStructCreate("dword;word;word;byte[8]")
    Local $pGUID = DllStructGetPtr($tGUID)
    ; Get the identifiers for the frame dimensions
    _GIF_GdipImageGetFrameDimensionsList($pBitmap$pGUID$iFrameDimensionsCount)
    If @error Then
        _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal)
        Return SetError(3, 0, 0)
    EndIf
    ; Number of frames
    Local $iFrameCount = _GIF_GdipImageGetFrameCount($pBitmap$pGUID)
    If @error Then
        _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal)
        Return SetError(4, 0, 0)
    EndIf
    ; Allocate needed global memory
    Local $pGIF = _GIF_MemGlobalAlloc(4 * (8 + 4 * @AutoItX64 + $iFrameCount), 64) ; GPTR
    If @error Then
        _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal)
        Return SetError(3, 0, 0)
    EndIf
    Local $tGIF = DllStructCreate("handle GIFThread;" & _
            "ptr CodeBuffer;" & _
            "hwnd ControlHandle;" & _
            "handle ImageList;" & _
            "bool ExitFlag;" & _
            "bool Transparent;" & _
            "dword CurrentFrame;" & _
            "dword NumberOfFrames;" & _
            "dword FrameDelay[" & $iFrameCount & "];", _
            $pGIF)
    DllStructSetData($tGIF"GIFThread", 0)
    DllStructSetData($tGIF"ControlHandle", 0)
    DllStructSetData($tGIF"ExitFlag", 0)
    DllStructSetData($tGIF"CurrentFrame", 0)
    ; Set number of frames
    DllStructSetData($tGIF"NumberOfFrames"$iFrameCount)
    ; Make GIF Control
    Local $fNewControl = False
    If Not $hGIFControl Then
        $fNewControl = True
        $hGIFControl = GUICtrlCreatePic(""$iLeft$iTop$iWidth$iHeight)
    EndIf
    ; If frame count is 1 then free what needs to be freed and return $pGIF. This requires no animation.
    If $iFrameCount = 1 Then
        Local $hGIFBitmap = _GIF_GdipCreateHBITMAPFromBitmap($pBitmap$iARGB)
        If $fDoResize Then _GIF_ResizeBitmap($hGIFBitmap$iWidth$iHeight)
        _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal)
        ; Render default image
        _GIF_DeleteObject(GUICtrlSendMsg($hGIFControl, 370, 0, $hGIFBitmap)) ; STM_SETIMAGE
        _GIF_DeleteObject($hGIFBitmap)
        Return $pGIF
    EndIf
    ; Make ImageList
    Local $hImageList = _GIF_ImageList_Create($iWidth$iHeight, 32, $iFrameCount; ILC_COLOR32
    If @error Then
        If $fNewControl Then GUICtrlDelete($hGIFControl)
        _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal$pGIF)
        Return SetError(4, 0, 0)
    EndIf
    ; Set imagelist
    DllStructSetData($tGIF"ImageList"$hImageList)
    Local $hBitmap
    For $j = 0 To $iFrameCount - 1 ; for all frames
        ; Select the frame
        _GIF_GdipImageSelectActiveFrame($pBitmap$pGUID$j)
        If @error Then ContinueLoop
        ; Fill the array with HBITMAPs
        $hBitmap = _GIF_GdipCreateHBITMAPFromBitmap($pBitmap$iARGB)
        If $fDoResize Then _GIF_ResizeBitmap($hBitmap$iWidth$iHeight)
        ; Add it to the ImageList
        _GIF_ImageList_Add($hImageList$hBitmap)
        If $j = 0 Then ; Export "static" GIF (first frame)
            ; Render default image
            _GIF_DeleteObject(GUICtrlSendMsg($hGIFControl, 370, 0, $hBitmap)) ; STM_SETIMAGE
            _GIF_DeleteObject($hBitmap)
        EndIf
        ; Delete it
        _GIF_DeleteObject($hBitmap)
    Next
    ; Get size of PropertyTagFrameDelay
    Local $iPropertyItemSize = _GIF_GdipGetPropertyItemSize($pBitmap, 0x5100) ; PropertyTagFrameDelay
    If @error Then
        If $fNewControl Then GUICtrlDelete($hGIFControl)
        _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal$pGIF)
        Return SetError(5, 0, 0)
    EndIf
    ; Raw structure for the call
    Local $tRawPropItem = DllStructCreate("byte[" & $iPropertyItemSize & "]")
    ; Fill the structure
    _GIF_GdipGetPropertyItem($pBitmap, 0x5100, $iPropertyItemSize, DllStructGetPtr($tRawPropItem)) ; PropertyTagFrameDelay
    If @error Then
        If $fNewControl Then GUICtrlDelete($hGIFControl)
        _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal$pGIF)
        Return SetError(6, 0, 0)
    EndIf
    ; Formatted structure in place of the raw
    Local $tPropItem = DllStructCreate("int Id;" & _
            "dword Length;" & _
            "word Type;" & _
            "ptr Value", _
            DllStructGetPtr($tRawPropItem))
    ; Read the "Length"
    Local $iSize = DllStructGetData($tPropItem"Length") / 4 ; 'Delay Time' is dword type. 4 is size of dword.
    ; Make new structure for the data
    Local $tPropertyData = DllStructCreate("dword[" & $iSize & "]", DllStructGetData($tPropItem"Value"))
    ; Read and fill array
    Local $iDelay
    For $j = 1 To $iFrameCount ; loop through all frames
        $iDelay = DllStructGetData($tPropertyData, 1, $j) * 10 ; 1 = 10 msec
        ; Corrections
        If Not $iDelay Then $iDelay = 130 ; interpreting 0 as 130 ms
        If $iDelay < 50 Then $iDelay = 50 ; will slow it down to prevent more extensive cpu usage
        ; Set delay
        DllStructSetData($tGIF"FrameDelay"$iDelay$j)
    Next
    ; Determining trancparency
    Local $fTransparent = True ; preset
    ; Get pixel color
    Local $iPixelColor = _GIF_GdipBitmapGetPixel($pBitmap, 0, 0) ; upper left pixel
    ; Color is ARGB. If A is set then it's not transparent
    If BitShift($iPixelColor, 24) Then $fTransparent = False
    ; Set transparency
    DllStructSetData($tGIF"Transparent"$fTransparent)
    ; Free
    _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal)
    ; Return sucess (pointer to allocated memory)
    Return $pGIF
EndFunc   ;==>_GIF_Create_pGIF

Func _GIF_CreateStreamOnHGlobal($hGlobal$iFlag = 1)
    Local $aCall = DllCall($hGIFDLL__OLE32"long""CreateStreamOnHGlobal""handle"$hGlobal"int"$iFlag"ptr*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[3]
EndFunc   ;==>_GIF_CreateStreamOnHGlobal

Func _GIF_GetObject($hObject$iSize$pObject)
    Local $aCall = DllCall($hGIFDLL__GDI32"int""GetObject""handle"$hObject"int"$iSize"ptr"$pObject)
    If @error Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_GetObject

Func _GIF_DeleteObject($hObject)
    Local $aCall = DllCall($hGIFDLL__GDI32"bool""DeleteObject""handle"$hObject)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_DeleteObject

Func _GIF_ImageList_GetIconSize($hImageList)
    Local $aOut[2] = [0, 0]
    Local $aCall = DllCall($hGIFDLL__COMCTL32"bool""ImageList_GetIconSize""handle"$hImageList"int*", 0, "int*", 0)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, $aOut)
    $aOut[0] = $aCall[2]
    $aOut[1] = $aCall[3]
    Return $aOut
EndFunc   ;==>_GIF_ImageList_GetIconSize

Func _GIF_ImageList_Create($iWidth$iHeight$iFlag$iInitial$iGrow = 0)
    Local $aCall = DllCall($hGIFDLL__COMCTL32"handle""ImageList_Create", _
            "int"$iWidth, _
            "int"$iHeight, _
            "dword"$iFlag, _
            "int"$iInitial, _
            "int"$iGrow)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_ImageList_Create

Func _GIF_ImageList_Add($hImageList$hBitmap)
    Local $aCall = DllCall($hGIFDLL__COMCTL32"int""ImageList_Add", _
            "handle"$hImageList, _
            "handle"$hBitmap, _
            "handle", 0)
    If @error Or $aCall[0] = -1 Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_ImageList_Add

Func _GIF_ImageList_Destroy($hImageList)
    Local $aCall = DllCall($hGIFDLL__COMCTL32"bool""ImageList_Destroy""handle"$hImageList)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_ImageList_Destroy

Func _GIF_ImageList_DrawEx($hImageList$iImageIndex$hDC$iXPos = 0, $iYPos = 0, $iWidth = 0, $iHeight = 0, $iBkColRef = -1, $iFgColRef = -1, $iStyle = 0)
    Local $aCall = DllCall($hGIFDLL__COMCTL32"bool""ImageList_DrawEx", _
            "handle"$hImageList, _
            "int"$iImageIndex, _
            "handle"$hDC, _
            "int"$iXPos, _
            "int"$iYPos, _
            "int"$iWidth, _
            "int"$iHeight, _
            "dword"$iBkColRef, _
            "dword"$iFgColRef, _
            "dword"$iStyle)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_ImageList_DrawEx

Func _GIF_CreateBitmapFromFile(ByRef $hGDIP$sFile, ByRef $iWidth, ByRef $iHeight)
    ; Initialize Gdip
    $hGDIP = _GIF_GdiplusStartup()
    If @error Then Return SetError(1, 0, 0)
    ; Create bitmap object out of the file
    Local $pBitmap = _GIF_GdipLoadImageFromFile($sFile)
    If @error Then
        _GIF_GdiplusShutdown($hGDIP)
        Return SetError(2, 0, 0)
    EndIf
    ; Get dimension
    _GIF_GdipGetImageDimension($pBitmap$iWidth$iHeight)
    If @error Then
        _GIF_FreeGdipAndMem($pBitmap$hGDIP)
        Return SetError(3, 0, 0)
    EndIf
    Return $pBitmap
EndFunc   ;==>_GIF_CreateBitmapFromFile

Func _GIF_CreateBitmapFromBinaryImage(ByRef $hGDIP, ByRef $hMemGlobal$bBinary, ByRef $iWidth, ByRef $iHeight)
    $bBinary = Binary($bBinary)
    ; Determine the size of binary data
    Local $iSize = BinaryLen($bBinary)
    ; Allocate global moveable memory in requred size
    $hMemGlobal = _GIF_MemGlobalAlloc($iSize, 2); GMEM_MOVEABLE
    If @error Then Return SetError(1, 0, 0)
    ; Get pointer to it
    Local $pMemory = _GIF_MemGlobalLock($hMemGlobal)
    If @error Then
        _GIF_MemGlobalFree($hMemGlobal)
        Return SetError(2, 0, 0)
    EndIf
    ; Make structure at that address
    Local $tBinary = DllStructCreate("byte[" & $iSize & "]"$pMemory)
    ; Fill it
    DllStructSetData($tBinary, 1, $bBinary)
    ; Create stream
    Local $pStream = _GIF_CreateStreamOnHGlobal($pMemory, 0)
    If @error Then
        _GIF_MemGlobalFree($hMemGlobal)
        Return SetError(3, 0, 0)
    EndIf
    ; Unlock memory (almost irrelevant)
    _GIF_MemGlobalUnlock($pMemory)
    ; Initialize Gdip
    $hGDIP = _GIF_GdiplusStartup()
    If @error Then
        _GIF_MemGlobalFree($hMemGlobal)
        Return SetError(4, 0, 0)
    EndIf
    ; Create bitmap object out of the stream
    Local $pBitmap = _GIF_GdipCreateBitmapFromStream($pStream)
    If @error Then
        _GIF_GdiplusShutdown($hGDIP)
        _GIF_MemGlobalFree($hMemGlobal)
        Return SetError(5, 0, 0)
    EndIf
    ; Get dimension
    _GIF_GdipGetImageDimension($pBitmap$iWidth$iHeight)
    If @error Then
        _GIF_FreeGdipAndMem($pBitmap$hGDIP$hMemGlobal)
        Return SetError(6, 0, 0)
    EndIf
    ; Call Release on stream object
    DllCallAddress("dword", DllStructGetData(DllStructCreate("ptr QueryInterface; ptr AddRef; ptr Release;", DllStructGetData(DllStructCreate("ptr pObj;"$pStream), "pObj")), "Release"), "ptr"$pStream)
    ; Return success
    Return $pBitmap
EndFunc   ;==>_GIF_CreateBitmapFromBinaryImage

Func _GIF_ResizeBitmap(ByRef $hBitmap$iNewWidth$iNewHeight)
    ; First to get available data for the bitmap
    Local $tBMP = DllStructCreate("long Type;long Width;long Height;long WidthBytes;word Planes;word BitsPixel;ptr Bits;")
    _GIF_GetObject($hBitmap, DllStructGetSize($tBMP), DllStructGetPtr($tBMP))
    ; Create bitmap object out of binary
    Local $pBitmap = _GIF_GdipCreateBitmapFromScan0(DllStructGetData($tBMP"Width"), DllStructGetData($tBMP"Height"), DllStructGetData($tBMP"WidthBytes"), 0x26200A, DllStructGetData($tBMP"Bits"))
    _GIF_GdipImageRotateFlip($pBitmap, 6) ; GdipCreateBitmapFromScan0 creates top-to-down bitmap and bmBits is the other way around, flip vertically therefore
    ; New empty bitmap in desired dimension
    Local $pNewBitmap = _GIF_GdipCreateBitmapFromScan0($iNewWidth$iNewHeight)
    Local $hGraphics = _GIF_GdipGetImageGraphicsContext($pNewBitmap)
    ; Draw the "old" bitmap here
    _GIF_GdipDrawImageRect($hGraphics$pBitmap, 0, 0, $iNewWidth$iNewHeight)
    ; Create bitmap out of new bitmap object
    Local $hNewBitmap = _GIF_GdipCreateHBITMAPFromBitmap($pNewBitmap)
    ; Clean
    _GIF_GdipDisposeImage($pBitmap)
    _GIF_GdipDeleteGraphics($hGraphics)
    _GIF_DeleteObject($hBitmap)
    _GIF_GdipDisposeImage($pNewBitmap)
    ; Replace old with new
    $hBitmap = $hNewBitmap
    ; That's it!
    Return 1
EndFunc   ;==>_GIF_ResizeBitmap

Func _GIF_GdiplusStartup()
    Local $tGdiplusStartupInput = DllStructCreate("dword GdiplusVersion;" & _
            "ptr DebugEventCallback;" & _
            "int SuppressBackgroundThread;" & _
            "int SuppressExternalCodecs")
    DllStructSetData($tGdiplusStartupInput"GdiplusVersion", 1)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdiplusStartup""dword_ptr*", 0, "ptr", DllStructGetPtr($tGdiplusStartupInput), "ptr", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[1]
EndFunc   ;==>_GIF_GdiplusStartup

Func _GIF_GdiplusShutdown($hGDIP)
    DllCall($hGIFDLL__GDIPLUS"none""GdiplusShutdown""dword_ptr"$hGDIP)
EndFunc   ;==>_GIF_GdiplusShutdown

Func _GIF_GdipDisposeImage($hImage)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipDisposeImage""handle"$hImage)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_GdipDisposeImage

Func _GIF_GdipGetImageDimension($pBitmap, ByRef $iWidth, ByRef $iHeight)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipGetImageDimension""ptr"$pBitmap"float*", 0, "float*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    $iWidth = $aCall[2]
    $iHeight = $aCall[3]
EndFunc   ;==>_GIF_GdipGetImageDimension

Func _GIF_GdipImageGetFrameDimensionsCount($pBitmap)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipImageGetFrameDimensionsCount""ptr"$pBitmap"dword*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[2]
EndFunc   ;==>_GIF_GdipImageGetFrameDimensionsCount

Func _GIF_GdipImageGetFrameDimensionsList($pBitmap$pGUID$iFrameDimensionsCount)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipImageGetFrameDimensionsList", _
            "ptr"$pBitmap, _
            "ptr"$pGUID, _
            "dword"$iFrameDimensionsCount)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_GdipImageGetFrameDimensionsList

Func _GIF_GdipImageGetFrameCount($pBitmap$pGUID)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipImageGetFrameCount", _
            "ptr"$pBitmap, _
            "ptr"$pGUID, _
            "dword*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[3]
EndFunc   ;==>_GIF_GdipImageGetFrameCount

Func _GIF_GdipImageSelectActiveFrame($pBitmap$pGUID$iFrameIndex)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipImageSelectActiveFrame", _
            "ptr"$pBitmap, _
            "ptr"$pGUID, _
            "dword"$iFrameIndex)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_GdipImageSelectActiveFrame

Func _GIF_GdipGetPropertyItemSize($pBitmap$iPropID)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipGetPropertyItemSize", _
            "ptr"$pBitmap, _
            "ptr"$iPropID, _
            "dword*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[3]
EndFunc   ;==>_GIF_GdipGetPropertyItemSize

Func _GIF_GdipGetPropertyItem($pBitmap$iPropID$iSize$pBuffer)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipGetPropertyItem", _
            "ptr"$pBitmap, _
            "dword"$iPropID, _
            "dword"$iSize, _
            "ptr"$pBuffer)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_GdipGetPropertyItem

Func _GIF_GdipBitmapGetPixel($pBitmap$iX$iY)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipBitmapGetPixel", _
            "ptr"$pBitmap, _
            "int"$iX, _
            "int"$iY, _
            "dword*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[4]
EndFunc   ;==>_GIF_GdipBitmapGetPixel

Func _GIF_GdipLoadImageFromFile($sFile)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipLoadImageFromFile""wstr"$sFile"ptr*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[2]
EndFunc   ;==>_GIF_GdipLoadImageFromFile

Func _GIF_GdipCreateBitmapFromScan0($iWidth$iHeight$iStride = 0, $iPixelFormat = 0x26200A, $pScan0 = 0)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipCreateBitmapFromScan0""int"$iWidth"int"$iHeight"int"$iStride"dword"$iPixelFormat"ptr"$pScan0"ptr*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[6]
EndFunc   ;==>_GIF_GdipCreateBitmapFromScan0

Func _GIF_GdipCreateBitmapFromStream($pStream)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipCreateBitmapFromStream""ptr"$pStream"ptr*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[2]
EndFunc   ;==>_GIF_GdipCreateBitmapFromStream

Func _GIF_GdipCreateHBITMAPFromBitmap($pBitmap$iARGB = 0xFF000000)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipCreateHBITMAPFromBitmap""ptr"$pBitmap"handle*", 0, "dword"$iARGB)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[2]
EndFunc   ;==>_GIF_GdipCreateHBITMAPFromBitmap

Func _GIF_GdipGetImageGraphicsContext($hImage)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipGetImageGraphicsContext""ptr"$hImage"ptr*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[2]
EndFunc   ;==>_GIF_GdipGetImageGraphicsContext

Func _GIF_GdipDrawImageRect($hGraphics$hImage$iX$iY$iWidth$iHeight)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipDrawImageRectI""ptr"$hGraphics"ptr"$hImage"int"$iX"int"$iY"int"$iWidth"int"$iHeight)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_GdipDrawImageRect

Func _GIF_GdipDeleteGraphics($hGraphics)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipDeleteGraphics""handle"$hGraphics)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_GdipDeleteGraphics

Func _GIF_GdipImageRotateFlip($hImage$iType)
    Local $aCall = DllCall($hGIFDLL__GDIPLUS"dword""GdipImageRotateFlip""handle"$hImage"dword"$iType)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_GdipImageRotateFlip

Func _GIF_FreeGdipAndMem($pBitmap = 0, $hGDIP = 0, $hMem = 0, $pGIF = 0)
    If $pBitmap Then _GIF_GdipDisposeImage($pBitmap)
    If $hGDIP Then _GIF_GdiplusShutdown($hGDIP)
    If $hMem Then _GIF_MemGlobalFree($hMem)
    If $pGIF Then _GIF_MemGlobalFree($pGIF)
EndFunc   ;==>_GIF_FreeGdipAndMem

Func _GIF_MemGlobalAlloc($iSize$iFlag)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"handle""GlobalAlloc""dword"$iFlag"dword_ptr"$iSize)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_MemGlobalAlloc

Func _GIF_MemGlobalFree($hMem)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"ptr""GlobalFree""handle"$hMem)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_GIF_MemGlobalFree

Func _GIF_MemGlobalLock($hMem)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"ptr""GlobalLock""handle"$hMem)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_MemGlobalLock

Func _GIF_MemGlobalUnlock($hMem)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"bool""GlobalUnlock""handle"$hMem)
    If @error Then Return SetError(1, 0, 0)
    If $aCall[0] Or _GIF_GetLastError() Then Return $aCall[0]
    Return 1
EndFunc   ;==>_GIF_MemGlobalUnlock

Func _GIF_GetLastError()
    Local $aCall = DllCall($hGIFDLL__KERNEL32"dword""GetLastError")
    If @error Then Return SetError(1, 0, -1)
    Return $aCall[0]
EndFunc   ;==>_GIF_GetLastError

Func _GIF_FindResourceEx($hModule$vResType$vResName$iResLang = 0)
    Local $sTypeType = "wstr"
    If $vResType == Number($vResType) Then $sTypeType = "int"
    Local $sNameType = "wstr"
    If $vResName == Number($vResName) Then $sNameType = "int"
    Local $aCall = DllCall($hGIFDLL__KERNEL32"handle""FindResourceExW", _
            "handle"$hModule, _
            $sTypeType$vResType, _
            $sNameType$vResName, _
            "int"$iResLang)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_FindResourceEx

Func _GIF_SizeofResource($hModule$hResource)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"int""SizeofResource""handle"$hModule"handle"$hResource)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_SizeofResource

Func _GIF_LoadResource($hModule$hResource)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"handle""LoadResource""handle"$hModule"handle"$hResource)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_LoadResource

Func _GIF_LockResource($hResource)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"ptr""LockResource""handle"$hResource)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_LockResource

Func _GIF_LoadLibraryEx($sModule$iFlag = 0)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"handle""LoadLibraryExW""wstr"$sModule"handle", 0, "dword"$iFlag)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_LoadLibraryEx

Func _GIF_FreeLibrary($hModule)
    Local $aCall = DllCall($hGIFDLL__KERNEL32"bool""FreeLibrary""handle"$hModule)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_GIF_FreeLibrary

Func _GIF_ResourceGetAsRaw($sModule$vResType$vResName$iResLang = 0)
    ; Load the module
    Local $hModule = _GIF_LoadLibraryEx($sModule, 2) ; LOAD_LIBRARY_AS_DATAFILE
    If @error Then Return SetError(1, 0, "")
    ; Find specified resource inside it
    Local $hResource = _GIF_FindResourceEx($hModule$vResType$vResName$iResLang)
    If @error Then
        _GIF_FreeLibrary($hModule)
        Return SetError(2, 0, "")
    EndIf
    ; Determine the size of the resource
    Local $iSizeOfResource = _GIF_SizeofResource($hModule$hResource)
    If @error Then
        _GIF_FreeLibrary($hModule)
        Return SetError(3, 0, "")
    EndIf
    ; Load it
    $hResource = _GIF_LoadResource($hModule$hResource)
    If @error Then
        _GIF_FreeLibrary($hModule)
        Return SetError(4, 0, "")
    EndIf
    ; Get pointer
    Local $pResource = _GIF_LockResource($hResource)
    If @error Then
        _GIF_FreeLibrary($hModule)
        Return SetError(5, 0, "")
    EndIf
    ; Make structure at that address
    Local $tBinary = DllStructCreate("byte[" & $iSizeOfResource & "]"$pResource)
    ; Collect data (this should be done before freeing the module)
    Local $bBinary = DllStructGetData($tBinary, 1)
    ; Free
    _GIF_FreeLibrary($hModule)
    ; Return data
    Return $bBinary
EndFunc   ;==>_GIF_ResourceGetAsRaw

Func _GIF_MakeBitmapFromRT_BITMAP($bBinary)
    Local $tBinary = DllStructCreate("byte[" & BinaryLen($bBinary) & "]")
    DllStructSetData($tBinary, 1, $bBinary)
    ; First dword is the size of the bitmap header
    Local $iHeaderSize = DllStructGetData(DllStructCreate("dword HeaderSize", DllStructGetPtr($tBinary)), "HeaderSize")
    Local $tBitmap$iMultiplier
    ; Check the size of the header (different formats)
    Switch $iHeaderSize
        Case 40
            $tBitmap = DllStructCreate("dword HeaderSize;" & _
                    "dword Width;" & _
                    "dword Height;" & _
                    "word Planes;" & _
                    "word BitPerPixel;" & _
                    "dword CompressionMethod;" & _
                    "dword Size;" & _
                    "dword Hresolution;" & _
                    "dword Vresolution;" & _
                    "dword Colors;" & _
                    "dword ImportantColors", _
                    DllStructGetPtr($tBinary))
            $iMultiplier = 4
        Case 12
            $tBitmap = DllStructCreate("dword HeaderSize;" & _
                    "word Width;" & _
                    "word Height;" & _
                    "word Planes;" & _
                    "word BitPerPixel", _
                    DllStructGetPtr($tBinary))
            $iMultiplier = 3
        Case Else
            Return SetError(1, 0, 0) ; unsupported format
    EndSwitch
    Local $iExponent = DllStructGetData($tBitmap"BitPerPixel")
    ; Construct the new BMP
    Local $tDIB = DllStructCreate("align 2;char Identifier[2];" & _
            "dword BitmapSize;" & _
            "short;" & _
            "short;" & _
            "dword BitmapOffset;" & _
            "byte Body[" & BinaryLen($bBinary) & "]")
    ; Fill the structure
    DllStructSetData($tDIB"Identifier""BM")
    DllStructSetData($tDIB"BitmapSize", BinaryLen($bBinary) + 14)
    ; Size of the bitmap. This data can be read from the read data, but somtimes it's not there and must be calculated.
    Local $iRawBitmapSize = DllStructGetData($tBitmap"Size")
    If $iRawBitmapSize Then ; data is found
        DllStructSetData($tDIB"BitmapOffset", BinaryLen($bBinary) - $iRawBitmapSize + 14)
    Else ; complication
        If $iExponent = 24 Then ; 24 bit per pixel is special case
            DllStructSetData($tDIB"BitmapOffset"$iHeaderSize + 14)
        Else ; this is pure math
            Local $iWidth = DllStructGetData($tBitmap"Width")
            Local $iHeight = DllStructGetData($tBitmap"Height")
            $iRawBitmapSize = 4 * Floor(($iWidth * $iExponent + 31) / 32) * $iHeight ; boundary
            Local $iOffset1 = BinaryLen($bBinary) - $iRawBitmapSize + 14
            Local $iOffset2 = 2 ^ $iExponent * $iMultiplier + $iHeaderSize + 14
            ; Get correct offset
            If $iOffset2 < $iOffset1 Then
                DllStructSetData($tDIB"BitmapOffset"$iOffset2)
            Else
                DllStructSetData($tDIB"BitmapOffset"$iOffset1 - 2)
            EndIf
        EndIf
    EndIf
    ; Set actual bitmap data
    DllStructSetData($tDIB"Body"$bBinary)
    ; Return the BMP data
    Return DllStructGetData(DllStructCreate("byte[" & DllStructGetSize($tDIB) & "]", DllStructGetPtr($tDIB)), 1)
EndFunc   ;==>_GIF_MakeBitmapFromRT_BITMAP

Func _GIF_SwapEndian($iValue$iSize = 0)
    If $iSize Then
        Local $sPadd = "00000000"
        Return Hex(BinaryMid($iValue, 1, $iSize)) & StringLeft($sPadd, 2 * ($iSize - BinaryLen($iValue)))
    EndIf
    Return Hex(Binary($iValue))
EndFunc   ;==>_GIF_SwapEndian

Func _GIF_GetGIFAssoc($iGIFId)
    Local $aArray = StringRegExp($sGIF__ASSOCSTRING_INTERNAL"(?i);" & $iGIFId & "\|(.*?);", 3)
    If @error Then Return 0
    Return Ptr($aArray[0])
EndFunc   ;==>_GIF_GetGIFAssoc
;============================================================================================
back to the source menu
test

Welcome to corz.org!

I'm always messing around with the back-end.. See a bug? Wait a minute and try again. Still see a bug? Mail Me!