;###################################################################################################################################
; SpriteUDF 1.0
; UDF Sprite :		Show Alpha-Channel Sprites on Desktop
; Author :			Faweyr
; Email :			faweyr1@web.de
; Date :			28.März.2010
; Language:			German
;###################################################################################################################################

#Include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>


#include-once
OnAutoItExitRegister("DeleteAllSprites")

Global $sSprite[1][14],$num = -1,$sBitmap,$sX,$xY,$sW,$sH,$sFrame,$sWindowX,$sWindowY,$sTime,$sObject,$sTrans,$sState,$nObject

;###################################################################################################################################
; Function:		CreateSprite
; Syntax:		$data = CreateSprite($sBitmap,$sX,$xY,$sW,$sH,$sFrame,$sWindowX,$sWindowY,$sTrans = 255,$sTime = 100)
; Note:			$data	=		Handle of Sprite
; 				$sBitmap =		Handle of Image [ _GDIPlus_ImageLoadFromFile() ]
; 				$sX/sY =		X and Y Position (Offset) of the Spritebitmap, where the Sprite is found
; 				$sW/H = 		Sprite itself in the picture
; 				$sFrame =		How many sprites are there in the picture [max 20]
;				$sWindowsX/Y =	The Desktop Position of the Sprite
; 				$sTrans =		The Transparens of the Sprite [0-255]
; 				$sTime =		How fast must the animation run [>= 50 ms]
;###################################################################################################################################

func CreateSprite($sBitmap,$sX,$xY,$sW,$sH,$sFrame,$sWindowX,$sWindowY,$sTrans = 255,$sTime = 100,$sState = 1)
	$num = $num+ 1
	redim $sSprite[$num+1][35]

	;Gui:
	$sSprite[$num][0] = GUICreate($num, $sW,$sH,$sWindowX,$sWindowY,-1, bitor($WS_EX_LAYERED,$WS_EX_TOOLWINDOW))
	GUISetState(@SW_SHOW,$sSprite[$num][0])
	;DC:
	$sSprite[$num][1]  = _WinAPI_GetDC(0)
	$sSprite[$num][2]  = _WinAPI_CreateCompatibleDC($sSprite[$num][1])
	;Source:
	$sSprite[$num][9] = DllStructCreate($tagPOINT)
	$sSprite[$num][3] = DllStructGetPtr($sSprite[$num][9])
	;Size:
	$sSprite[$num][10]  = DllStructCreate($tagSIZE)
	$sSprite[$num][4]  = DllStructGetPtr($sSprite[$num][10])
	DllStructSetData($sSprite[$num][10], "X", $sW)
	DllStructSetData($sSprite[$num][10], "Y", $sH)
	;Blend:
	$sSprite[$num][11] = DllStructCreate($tagBLENDFUNCTION)
	$sSprite[$num][5]  = DllStructGetPtr($sSprite[$num][11])
	DllStructSetData($sSprite[$num][11], "Alpha" , $sTrans)
	DllStructSetData($sSprite[$num][11], "Format", 1)
	;Bitmaps:
	$sSprite[$num][6] = $sTime
	$sSprite[$num][7] = $sFrame
	$sSprite[$num][8] = 1	;aktuelles Sprite
	$sSprite[$num][12] = TimerInit()	;Timer
	$sSprite[$num][13] = 1	;Sleep-Mode
	$sSprite[$num][14] = $sState
	for $i = 0 to $sFrame step 1
		$sSprite[$num][15+$i] = _GDIPlus_BitmapCloneArea($sBitmap, $sX+$sW*$i,$xY, $sW,$sH,$GDIP_PXF32ARGB)
	Next
	Return $num
EndFunc

	
;###################################################################################################################################
; Function:		RedrawSprites
; Syntax:		RedrawSprites()
; Note:			Must be in the Main-Loop
;###################################################################################################################################

func RedrawSprites()
	;Geht jedes Sprite durch:
	for $i = 0 to $num step 1
		
		If TimerDiff($sSprite[$i][12]) >= $sSprite[$i][6] and $sSprite[$i][13] = 1 and $sSprite[$i][0] <> 0 then
			$sSprite[$i][12] = TimerInit()
			;Setzt nächtes Frame:
			If $sSprite[$i][8] <= $sSprite[$i][7] then
				$sSprite[$i][8] = 1 + $sSprite[$i][8]
			Else
				If $sSprite[$i][14] = 0 then
					DeleteSprite($i)
					ContinueLoop
				endif
				$sSprite[$i][8] = 1
			endif
			
			;Bringt nächstes Frame auf den Bildschirm:
			$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($sSprite[$i][15+$sSprite[$i][8]])
			$hOld    = _WinAPI_SelectObject($sSprite[$i][2], $hBitmap)
			;aktuellisiert das Fenster:
			_WinAPI_UpdateLayeredWindow($sSprite[$i][0], $sSprite[$i][1], 0, $sSprite[$i][4],$sSprite[$i][2], $sSprite[$i][3], 0, $sSprite[$i][5], $ULW_ALPHA)
			;Gibt Handle wieder frei:
			_WinAPI_SelectObject($sSprite[$i][2], $hOld)
			_WinAPI_DeleteObject($hBitmap)
		endif
	Next
EndFunc

;###################################################################################################################################
; Function:		DeleteSprite
; Syntax:		DeleteSprite($sObject)
; Note:			$sObject =		Handle of the Sprite to delete
;###################################################################################################################################

func DeleteSprite($sObject)
	GUIDelete($sSprite[$sObject][0])
	$sSprite[$sObject][0] = 0
	_WinAPI_ReleaseDC   (0, $sSprite[$sObject][1])
	_WinAPI_DeleteDC    ($sSprite[$sObject][2])
	
	for $i = 0 to $sSprite[$sObject][7] step 1
		_GDIPlus_ImageDispose($sSprite[$sObject][15+$i])
	Next
EndFunc

;###################################################################################################################################
; Function:		DeleteAllSprites
; Syntax:		DeleteAllSprites()
; Note:			Delete all Sprites
;###################################################################################################################################

func DeleteAllSprites()
	for $i = 0 to $num step 1
		If $sSprite[$i][0] <> 0 then
			GUIDelete($sSprite[$i][0])
			_WinAPI_ReleaseDC   (0, $sSprite[$i][1])
			_WinAPI_DeleteDC    ($sSprite[$i][2])
			for $n = 0 to $sSprite[$i][7] step 1
				_GDIPlus_ImageDispose($sSprite[$i][15+$n])
			Next
		endif
	Next
	redim $sSprite[1][15]
	$num = -1
EndFunc

;###################################################################################################################################
; Function:		SetSpriteTransparens
; Syntax:		SetSpriteTransparens($sObject,$sTrans)
; Note:			$sObject =		Handle of the Sprite
;				$sTrans = 		The Transparents of the Sprite [0-255]
;###################################################################################################################################

func SetSpriteTransparens($sObject,$sTrans)
	$sSprite[$sObject][11] = DllStructCreate($tagBLENDFUNCTION)
	$sSprite[$sObject][5]  = DllStructGetPtr($sSprite[$sObject][11])
	DllStructSetData($sSprite[$sObject][11], "Alpha" , $sTrans)
	DllStructSetData($sSprite[$sObject][11], "Format", 1)
EndFunc

;###################################################################################################################################
; Function:		SetSpriteSpeed
; Syntax:		SetSpriteSpeed($sObject,$sTime)
; Note:			$sObject =		Handle of the Sprite
;				$sTrans = 		How fast must the animation run [>= 50 ms]
;###################################################################################################################################

func SetSpriteSpeed($sObject,$sTime)
	$sSprite[$sObject][6] = $sTime
EndFunc

;###################################################################################################################################
; Function:		GetSpriteSpeed
; Syntax:		$data = GetSpriteSpeed($sObject)
; Note:			$sObject =		Handle of the Sprite
;				$data = 		Speed of the Animation [ms]
;###################################################################################################################################

func GetSpriteSpeed($sObject)
	Return $sSprite[$sObject][6]
EndFunc

;###################################################################################################################################
; Function:		SetSpritePos
; Syntax:		SetSpritePos($sObject,$sX,$sY)
; Note:			$sObject =		Handle of the Sprite
;				$sX/sY = 		The Desktop Position of the Sprite
;###################################################################################################################################

func SetSpritePos($sObject,$sX,$sY)
	WinMove ( $sSprite[$sObject][0], "", $sX,$sY)
EndFunc

;###################################################################################################################################
; Function:		SetSpriteMode
; Syntax:		SetSpriteMode($sObject,$sState)
; Note:			$sObject =		Handle of the Sprite
;				$sState = 		1 = Animation run
;								0 = Animation sleep
;###################################################################################################################################

func SetSpriteMode($sObject,$sState)	;1=run,0=sleep
	$sSprite[$sObject][13] = $sState
EndFunc

;###################################################################################################################################
; Function:		SetSpriteFrame
; Syntax:		SetSpriteFrame($sObject,$sFrame)
; Note:			$sObject =		Handle of the Sprite
;				$sFrame = 		Number of Frame to set
;								
;###################################################################################################################################

func SetSpriteFrame($sObject,$sFrame)	;1=run,0=sleep
	$sSprite[$sObject][7] = $sFrame
EndFunc

;###################################################################################################################################
; Function:		GetSpriteMove
; Syntax:		$data = GetSpriteMove($sObject)
; Note:			$sObject =		Handle of the Sprite
;				$data =			1 = Animation run
;								0 = Animation sleep
;###################################################################################################################################

func GetSpriteMode($sObject)
	Return $sSprite[$sObject][13]
EndFunc

;###################################################################################################################################
; Function:		GetSpriteCoord
; Syntax:		$data = GetSpriteCoord($sObject)
; Note:			$sObject =		Handle of the Sprite
;				$data[0] =		X-Position
;				$data[1] =		y-Position
;				$data[2] =		Width of the Sprite
;				$data[3] =		Height of the Sprite
;###################################################################################################################################

func GetSpriteCoord($sObject)
	Return WinGetPos ($sSprite[$sObject][0])
EndFunc

;###################################################################################################################################
; Function:		GetSpriteCollision
; Syntax:		$data = GetSpriteCollision($sObject,$nObject)
; Note:			$sObject =		Handle of the Sprite
;				$nObject =		Handle of another Sprite
;				$data =			1 = collide
;								0 = don´t collide
;###################################################################################################################################

func GetSpriteCollision($sObject,$nObject)
	$sRect = WinGetPos ($sSprite[$sObject][0])
	$nRect = WinGetPos ($sSprite[$nObject][0])
	If $sRect[0]+$sRect[2] > $nRect[0] and $sRect[0] < $nRect[0]+$nRect[2] and     $sRect[1]+$sRect[3] > $nRect[1] and $sRect[1] < $nRect[1]+$nRect[2] Then Return 1
EndFunc

;###################################################################################################################################
; Function:		GetSpriteRect
; Syntax:		$data = GetSpriteRect($sObject,$sX,$sY,$sW,$sH)
; Note:			$sObject =		Handle of the Sprite
;				$sX/$sY =		Position of the Rect to check
;				$xW/$sH =		Size of the Rect
;				$data = 		1 = True	(Sprite is inside)
;								0 = False	(Sprite is outside)
;###################################################################################################################################

func GetSpriteRect($sObject,$sX,$sY,$sW,$sH)
	$sRect = WinGetPos ($sSprite[$sObject][0])
	If $sRect[0]+$sRect[2] > $sX and $sRect[0] < $sX+$sW and     $sRect[1]+$sRect[3] > $sY and $sRect[1] < $sY+$sH Then Return 1
EndFunc

;###################################################################################################################################
; Function:		SetSpriteTopmost
; Syntax:		SetSpriteTopmost($sObject,$sState)
; Note:			$sObject =		Handle of the Sprite
;				$sState =		1 = Set Sprite on Top
;								0 = Change Topmost back
;###################################################################################################################################

func SetSpriteTopmost($sObject,$sState)
	WinSetOnTop($sSprite[$sObject][0], "", $sState)
EndFunc

;###################################################################################################################################
; Function:		SetSpriteAnimation
; Syntax:		SetSpriteAnimation($sObject,$sBitmap,$sX,$xY,$sW,$sH,$sFrame,$sTime)
; Note:			$sObject =		Handle of the Sprite
;				$sBitmap =		Handle of Image [ _GDIPlus_ImageLoadFromFile() ]
; 				$sX/sY =		X and Y Position (Offset) of the Spritebitmap, where the Sprite is found
; 				$sW/H = 		Sprite itself in the picture
; 				$sFrame =		How many sprites are there in the picture [max 20]
; 				$sTime =		How fast must the animation run [>= 50 ms]
;###################################################################################################################################

func SetSpriteAnimation($sObject,$sBitmap,$sX,$xY,$sW,$sH,$sFrame,$sTime,$sState = 1)
	;Size:
	$sSprite[$sObject][10]  = DllStructCreate($tagSIZE)
	$sSprite[$sObject][4]  = DllStructGetPtr($sSprite[$sObject][10])
	DllStructSetData($sSprite[$sObject][10], "X", $sW)
	DllStructSetData($sSprite[$sObject][10], "Y", $sH)
	;Bitmaps:
	$sSprite[$sObject][6] = $sTime
	$sSprite[$sObject][7] = $sFrame
	$sSprite[$sObject][8] = 1	;aktuelles Sprite
	$sSprite[$sObject][12] = TimerInit()	;Timer
	$sSprite[$sObject][14] = $sState
	;alte Bitmaps löschen
	for $i = 0 to $sSprite[$sObject][7] step 1
		_GDIPlus_ImageDispose($sSprite[$sObject][15+$i])
	Next
	;neue Bitmaps laden:
	for $i = 0 to $sFrame step 1
		$sSprite[$sObject][15+$i] = _GDIPlus_BitmapCloneArea($sBitmap, $sX+$sW*$i,$xY, $sW,$sH,$GDIP_PXF32ARGB)
	Next
EndFunc

;###################################################################################################################################
; Function:		GetSpriteFrame
; Syntax:		$data = GetSpriteFrame($sObject)
; Note:			$sObject =		Handle of the Sprite
;				$data = 		Actuelly Frame
;###################################################################################################################################

func GetSpriteFrame($sObject)
	Return $sSprite[$sObject][8]
EndFunc
	
;###################################################################################################################################
; Function:		MouseOverSprite
; Syntax:		$data = MouseOverSprite($sObject)
; Note:			$sObject =		Handle of the Sprite
;				$data = 		1 = True
;								0 = False
;###################################################################################################################################

func MouseOverSprite($sObject)
	$sRect = WinGetPos ($sSprite[$sObject][0])
	$sMouse = MouseGetPos ()
	If $sRect[0]+$sRect[2] > $sMouse[0] and $sRect[0] < $sMouse[0] and     $sRect[1]+$sRect[3] > $sMouse[1] and $sRect[1] < $sMouse[1] Then Return 1
EndFunc

;###################################################################################################################################
; Function:		GetSpriteCount
; Syntax:		$data = GetSpriteCount()
; Note:			$data = 		Number of Sprites on the Screen
;###################################################################################################################################

func GetSpriteCount()
	Local $obj = $num
	for $i = 0 to $num step 1
		If $sSprite[$i][0] = 0 then $obj = $obj-1
	Next
	Return $obj
EndFunc

;###################################################################################################################################
; Function:		_GetTaskBarProps
; Syntax:		$data = _GetTaskBarProps($hProperty="")
; Note:			$hProperty =	"TOP" = Give the Top Position of the TaskBar back
;								"LEFT" = Give the Left Position of the TaskBar back
;								"HEIGHT" = Give the Height of the TaskBar back
;								"WIDTH" = Give the Width of the TaskBar back
;				$data = 		Position
;###################################################################################################################################

Func GetTaskBarProps($hProperty="")
    Local $tRect = DllStructCreate("long;long;long;long"), $hWnd, $ret
    $hProperty = StringUpper(StringStripWS($hProperty, 3))
    $ret = DllCall("user32.dll", 'long', "FindWindowA", 'str', "Shell_traywnd", 'str', "")
    $hWnd = $ret[0]
    DllCall("User32.dll", "int", "GetWindowRect", "hwnd", $hWnd, "ptr", DllStructGetPtr($tRect))
    Local $left   = DllStructGetData($tRect, 1)
    Local $top    = DllStructGetData($tRect, 2)
    Local $right  = DllStructGetData($tRect, 3)
    Local $bottom = DllStructGetData($tRect, 4)
    If $hProperty = "" Then
        Local $aOut[4] = [$left, $top, $right, $bottom]
        Return $aOut
    EndIf
    Switch $hProperty
        Case "TOP"
            Return $top
        Case "LEFT"
            Return $left
        Case "HEIGHT"
            Return $bottom - $top
        Case "WIDTH"
            Return $right - $left
        Case "ALIGN"
            If $top < 1 Then
                If $left < 1 Then
                    If $bottom > $right Then Return 1
                    If $right > $bottom Then Return 3
                EndIf
            EndIf
            If $top < 1 Then
                If $left > 0 Then Return 2
            EndIf
            If $left < 1 Then
                If $top > 0 Then Return 4
            EndIf
    EndSwitch
EndFunc 


;###################################################################################################################################
; Function:		ResourceLoadImage
; Syntax:		$data = _ResourceLoadImage($DLL, $ResName)
; Note:			Load Png-Images with Alpha Channel from Ressource
;				$DLL =		Path of the Dll [@scriptdir & "\gfx.dll"]
;				$ResName = 	Name of Ressource
;				$data = 	Handle of the Image
;###################################################################################################################################

Func ResourceLoadImage($DLL, $ResName)
    Local $hInstance, $InfoBlock, $GlobalMemoryBlock, $MemoryPointer, $ResSize, $hData, $pData, $pStream, $dll2, $pBitmap
    $hInstance = DllCall("kernel32.dll", "int", "LoadLibrary", "str", $DLL)
    $InfoBlock = DllCall("kernel32.dll", "int", "FindResourceA", "int", $hInstance[0], "str", $ResName, "long", 10)
    $ResSize = DllCall("kernel32.dll", "dword", "SizeofResource", "int", $hInstance[0], "int", $InfoBlock[0])
    $GlobalMemoryBlock = DllCall("kernel32.dll", "int", "LoadResource", "int", $hInstance[0], "int", $InfoBlock[0])
    $MemoryPointer = DllCall("kernel32.dll", "int", "LockResource", "int", $GlobalMemoryBlock[0])
    DllCall("Kernel32.dll", "int", "FreeLibrary", "str", $hInstance[0])
    $hData = _MemGlobalAlloc($ResSize[0], 2)
    $pData = _MemGlobalLock($hData)
    _MemMoveMemory($MemoryPointer[0], $pData, $ResSize[0])
    _MemGlobalUnlock($hData)
    $pStream = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "int", $hData, "long", 1, "Int*", 0)
	
    $pBitmap = DllCall($ghGDIPDll, "int", "GdipCreateBitmapFromStream", "ptr", $pStream[3], "int*", 0)
    $DLL = DllStructCreate("Uint", $pStream[3])
    $dll2 = DllStructCreate("uInt", DllStructGetData($DLL, 1) + 8)
    DllCall("", "UInt", DllStructGetData($dll2, 1), "UInt", $pStream[3])
    _WinAPI_DeleteObject($pStream[3])
    $pStream[3] = 0
    _MemGlobalFree($hData)
    Return $pBitmap[2]
EndFunc 

;###################################################################################################################################
; Function:		RessourceSetImage
; Syntax:		RessourceSetImage($sImage,$sName,$sDll)
; Note:			$sImage = 	$Path of the Image [@scriptdir & "\image.png"]
;				$sName = 	Name of Ressource
;				$sDll = 	$Path of the Dll [@scriptdir & "\gfx.dll"]
;###################################################################################################################################

func RessourceSetImage($sImage,$sName,$sDll)
	$sLine="ResHacker.exe -addoverwrite "&$sDll&", "&$sDll&", " & $sImage & ", rcdata, " & $sName & ", 0"
	ConsoleWrite($sLine & @LF)
	RunWait($sLine)
EndFunc

;###################################################################################################################################
; Function:		SetCursor
; Syntax:		SetCursor($s_file, $i_cursor)
; Note:			$s_file = 		Path of new Cursorimage (ani, cur)
;				$i_cursor = 	Which Cursor
;###################################################################################################################################

Func SetCursor($s_file, $i_cursor)
   Local $newhcurs, $lResult
   $newhcurs = DllCall("user32.dll", "int", "LoadCursorFromFile", "str", $s_file)
   If Not @error Then
      $lResult = DllCall("user32.dll", "int", "SetSystemCursor", "int", $newhcurs[0], "int", $i_cursor)
      If Not @error Then
         $lResult = DllCall("user32.dll", "int", "DestroyCursor", "int", $newhcurs[0])
      Else
         MsgBox(0, "Error", "Failed SetSystemCursor")
      EndIf
   Else
      MsgBox(0, "Error", "Failed LoadCursorFromFile")
  EndIf
  
EndFunc  ;==>_SetCursor