#include-once
#include <GDIPlus.au3>

Func _Garfik_Startup($iWidth, $iHeight, $iFPS = 30)
	Local $aReturn[10], $hHBitmap
	_GDIPlus_Startup()
	$aReturn[0] = GUICreate('', $iWidth, $iHeight, 0, 0, 0x80000000)
	$aReturn[1] = _WinAPI_GetWindowDC($aReturn[0])
	$aReturn[2] = _WinAPI_CreateCompatibleDC($aReturn[1])
	$aReturn[3] = _WinAPI_CreateCompatibleDC($aReturn[1])
	$aReturn[4] = $iWidth
	$aReturn[5] = $iHeight
	$aReturn[6] = 1000 / $iFPS
	$aReturn[7] = TimerInit()
	$aReturn[8] = DllStructCreate('int64')
	$aReturn[9] = DllOpen('ntdll.dll')
	$hHBitmap = _WinAPI_CreateCompatibleBitmap($aReturn[1], $aReturn[4], $aReturn[5])
	_WinAPI_DeleteObject(_WinAPI_SelectObject($aReturn[2], $hHBitmap))
	_WinAPI_DeleteObject($hHBitmap)
	$hHBitmap = _WinAPI_CreateCompatibleBitmap($aReturn[1], $aReturn[4], $aReturn[5])
	_WinAPI_DeleteObject(_WinAPI_SelectObject($aReturn[3], $hHBitmap))
	_WinAPI_DeleteObject($hHBitmap)
	GUISetState(@SW_SHOW, $aReturn[0])
	Return $aReturn
EndFunc   ;==>_Garfik_Startup

Func _Garfik_ObjectCreate($hGarfik, $hBitmap, $iX, $iY, $iWidth, $iHeight)
	Local $aReturn[4], $hClone, $hHBitmap
	$aReturn[0] = _WinAPI_CreateCompatibleDC($hGarfik[1])
	$aReturn[1] = $iWidth
	$aReturn[2] = $iHeight
	$aReturn[3] = 0
	$hClone = _GDIPlus_BitmapCloneArea($hBitmap, $iX, $iY, $iWidth, $iHeight)
	$hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hClone)
	_WinAPI_DeleteObject(_WinAPI_SelectObject($aReturn[0], $hHBitmap))
	_WinAPI_DeleteObject($hHBitmap)
	_GDIPlus_BitmapDispose($hClone)
	Return $aReturn
EndFunc   ;==>_Garfik_ObjectCreate

Func _Garfik_ObjectCreateFromMask($hGarfik, $hMask, $iX, $iY, $iWidth, $iHeight)
	Local $aReturn[4], $hClone, $hHBitmap
	$aReturn[0] = _WinAPI_CreateCompatibleDC($hGarfik[1])
	$aReturn[1] = $iWidth
	$aReturn[2] = $iHeight
	$aReturn[3] = _WinAPI_CreateCompatibleDC($hGarfik[1])
	$hClone = _GDIPlus_BitmapCloneArea($hMask[0], $iX, $iY, $iWidth, $iHeight)
	$hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hClone)
	_WinAPI_DeleteObject(_WinAPI_SelectObject($aReturn[0], $hHBitmap))
	_WinAPI_DeleteObject($hHBitmap)
	_GDIPlus_BitmapDispose($hClone)
	$hClone = _GDIPlus_BitmapCloneArea($hMask[1], $iX, $iY, $iWidth, $iHeight)
	$hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hClone)
	_WinAPI_DeleteObject(_WinAPI_SelectObject($aReturn[3], $hHBitmap))
	_WinAPI_DeleteObject($hHBitmap)
	_GDIPlus_BitmapDispose($hClone)
	Return $aReturn
EndFunc   ;==>_Garfik_ObjectMaskCreate

Func _Garfik_Clear($hGarfik)
	_WinAPI_BitBlt($hGarfik[2], 0, 0, $hGarfik[4], $hGarfik[5], $hGarfik[3], 0, 0, 0x00CC0020)
EndFunc   ;==>_Garfik_Clear

Func _Garfik_DrawObject($hGarfik, $hObject, $iX, $iY)
	If $hObject[3] Then
		_WinAPI_BitBlt($hGarfik[2], $iX, $iY, $hObject[1], $hObject[2], $hObject[0], 0, 0, 0x008800C6)
		_WinAPI_BitBlt($hGarfik[2], $iX, $iY, $hObject[1], $hObject[2], $hObject[3], 0, 0, 0x00EE0086)
	Else
		_WinAPI_BitBlt($hGarfik[2], $iX, $iY, $hObject[1], $hObject[2], $hObject[0], 0, 0, 0x00CC0020)
	EndIf
EndFunc   ;==>_Garfik_DrawObject

Func _Garfik_SetBackground($hGarfik, $hBitmap)
	Local $hClone, $hHBitmap
	$hClone = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $hGarfik[4], $hGarfik[5])
	$hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hClone)
	_WinAPI_DeleteObject(_WinAPI_SelectObject($hGarfik[3], $hHBitmap))
	_WinAPI_DeleteObject($hHBitmap)
	_GDIPlus_BitmapDispose($hClone)
EndFunc   ;==>_Garfik_SetBackground

Func _Garfik_ObjectDelete($hObject)
	If $hObject[3] Then
		_WinAPI_DeleteDC($hObject[0])
		_WinAPI_DeleteDC($hObject[3])
	Else
		_WinAPI_DeleteDC($hObject[0])
	EndIf
EndFunc   ;==>_Garfik_ObjectDelete

Func _Garfik_Update(ByRef $hGarfik)
	Local $iDiff
	_WinAPI_BitBlt($hGarfik[1], 0, 0, $hGarfik[4], $hGarfik[5], $hGarfik[2], 0, 0, 0x00CC0020)
	$iDiff = Round($hGarfik[6] - TimerDiff($hGarfik[7]), 4)
	If $iDiff > 0 Then DllStructSetData($hGarfik[8], 1, $iDiff * - 10000)
	DllCall($hGarfik[9], 'dword', 'ZwDelayExecution', 'int', 0, 'ptr', DllStructGetPtr($hGarfik[8]))
	$hGarfik[7] = TimerInit()
EndFunc   ;==>_Garfik_Update

Func _Garfik_Shutdown(ByRef $hGarfik)
	$hGarfik[8] = 0
	_WinAPI_DeleteDC($hGarfik[3])
	_WinAPI_DeleteDC($hGarfik[2])
	_WinAPI_ReleaseDC($hGarfik[0], $hGarfik[1])
	_GDIPlus_Shutdown()
EndFunc   ;==>_Garfik_Shutdown

Func _Garfik_MaskCreate($hBitmap)
	Local $iWidth, $iHeight, $hClone, $hBitmapData, $hReturn1Data, $hReturn2Data, $dBitmapStruct, $dReturn1Struct, $dReturn2Struct, $aReturn[2], $sCode, $dCode
	$iWidth = _GDIPlus_ImageGetWidth($hBitmap)
	$iHeight = _GDIPlus_ImageGetHeight($hBitmap)
	$aReturn[0] = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $iWidth, $iHeight)
	$aReturn[1] = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $iWidth, $iHeight)
	$hBitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $iWidth, $iHeight)
	$hReturn1Data = _GDIPlus_BitmapLockBits($aReturn[0], 0, 0, $iWidth, $iHeight, 3)
	$hReturn2Data = _GDIPlus_BitmapLockBits($aReturn[1], 0, 0, $iWidth, $iHeight, 3)
	$sCode = '0x8B4C241083E9048B54240401CAB8FF0000008B1A81E3000000FFC1EB1829D8BB01010100F7E305000000FF8B54240801CA89028B54240401CA8B028B1A25FFFFFF0081E3000000FFC1EB18F7E3BBFF000000F7F305000000FF8B54240C01CA890283F900759EC3'
	$dCode = DllStructCreate('byte[' & StringLen($sCode) / 2 - 1 & ']')
	DllStructSetData($dCode, 1, $sCode)
	DllCall('user32.dll', 'int', 'CallWindowProcW', 'ptr', DllStructGetPtr($dCode), 'ptr', DllStructGetData($hBitmapData, 'Scan0'), 'ptr', DllStructGetData($hReturn1Data, 'Scan0'), 'ptr', DllStructGetData($hReturn2Data, 'Scan0'), 'int', $iWidth * $iHeight * 4)
	_GDIPlus_BitmapUnlockBits($hBitmap, $hBitmapData)
	_GDIPlus_BitmapUnlockBits($aReturn[0], $hReturn1Data)
	_GDIPlus_BitmapUnlockBits($aReturn[1], $hReturn2Data)
	$dCode = 0
	$dBitmapStruct = 0
	$dReturn1Struct = 0
	$dReturn2Struct = 0
	Return $aReturn
EndFunc   ;==>_CreateMask

Func _Garfik_MaskDelete($hMask)
	_GDIPlus_BitmapDispose($hMask[0])
	_GDIPlus_BitmapDispose($hMask[1])
EndFunc
