;coded by UEZ 2011 build 2011-04-06
;~ #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#AutoIt3Wrapper_Run_Obfuscator=y
#Obfuscator_Parameters=/sf /sv /om /cs=0 /cn=0
#AutoIt3Wrapper_Run_After=del /f /q "%scriptdir%\%scriptfile%_Obfuscated.au3"
#AutoIt3Wrapper_UseUpx=y
#AutoIt3Wrapper_UPX_Parameters=--brute --crp-ms=999999 --all-methods --all-filters
;~ #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

#include <Date.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#Include <Timers.au3>
#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)

Global $hGUI, $hGraphics, $hBackbuffer, $hBitmap, $hPen1, $hPen2, $hPen3, $hPen4
Global $iX = 600, $iY = $iX
Global Const $p2_hm = $iX / 35
Global Const $p3_hm = $iX / 35
Global Const $p4_hm = $iX / 100
Global $newY = $iX, $newX = $iY
Global Const $minSize = $iX * 0.25
Global Const $maxSize = $iX * 1.5
Global Const $cX = $iX * 0.5, $cY = $iY * 0.5
Global Const $deg = ACos(-1) / 180
Global Const $radius = $iX * 0.85, $cR = $radius * 0.50
Global Const $cR1 = $cR * 0.90, $cR2 = $cR * 0.20
Global Const $cR3 = $cR * 0.80, $cR4 = $cR * 0.15
Global Const $cR5 = $cR * 0.50, $cR6 = $cR * 0.10
Global $sek = @SEC * 6 - 90
Global $min = @MIN * 6 + (@SEC / 10) - 90
Global $std = @HOUR * 30 + (@MIN / 2) - 90
Global Const $fs = $iY / 30, $tms = $iY / 20, $tmh = $iY * 0.725
Global $x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4, $x5, $x6, $y5, $y6, $tm
; Initialize GDI+
_GDIPlus_Startup()

$hGUI = GUICreate("GDI+ Simple Clock by UEZ 2011", $iX, $iY, -1, -1, $WS_SIZEBOX)
If @OSBuild < 7600 Then WinSetTrans($hGui,"", 0xFF) ;workaround for XP machines when alpha blending is activated on _GDIP
GUISetState()

$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($iX, $iY, $hGraphics)
$hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

; Using antialiasing
_GDIPlus_GraphicsSetSmoothingMode($hBackbuffer, 2)

; Create a Pen object
$hPen1 = _GDIPlus_PenCreate(0xFF800010, 4)
$hPen2 = _GDIPlus_PenCreate(0xA01010F0,  $p2_hm)
$hPen3 = _GDIPlus_PenCreate(0xA01010F0,  $p3_hm)
$hPen4 = _GDIPlus_PenCreate(0x9010D040,  $p4_hm)

Global Const  $LineCapRound = 2,  $LineCapTriangle = 3, $DashCapFlat = 0
Global $hPath, $hCustomLineCap, $avCaps
Global $avPoints[3][2] = [[2], [0, 0], [0, 0]]

$hPath = _GDIPlus_PathCreate()
_GDIPlus_PathAddLines($hPath, $avPoints)
$hCustomLineCap = _GDIPlus_CustomLineCapCreate(0, $hPath)
_GDIPlus_CustomLineCapSetStrokeCaps($hCustomLineCap, $LineCapTriangle, $LineCapRound)
$avCaps = _GDIPlus_CustomLineCapGetStrokeCaps($hCustomLineCap)
_GDIPlus_PenSetLineCap($hPen2, $avCaps[0], $avCaps[1], $DashCapFlat)
_GDIPlus_PenSetLineCap($hPen3, $avCaps[0], $avCaps[1], $DashCapFlat)
_GDIPlus_PenSetLineCap($hPen4, $avCaps[0], $avCaps[1], $DashCapFlat)

Global $ws = WinGetPos($hGUI)
Global $ratio = $ws[3] / $ws[2]
Global $font = "Comic Sans MS"
If FileExists(@WindowsDir & "\fonts\showg.ttf") Then $font = "Showcard Gothic"

GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")

AdlibRegister("Ticker", 50)

GUIRegisterMsg($WM_SIZE, "WM_SIZE")
GUIRegisterMsg($WM_SIZING, "WM_SIZING")
GUIRegisterMsg($WM_ERASEBKGND, "WM_ERASEBKGND")
GUIRegisterMsg($WM_GETMINMAXINFO, "WM_GETMINMAXINFO")

Global $timer = 100,  $speak = False, $speak_init = True, $SpeakingClock = True
Global $oVoice = ObjCreate("SAPI.SpVoice")
If @error Then
	$speak_init = False
Else
	$oVoice.Rate = -3
EndIf

GUIRegisterMsg($WM_TIMER, "Draw") ;$WM_TIMER = 0x0113
DllCall("User32.dll", "int", "SetTimer", "hwnd", $hGUI, "int", 0, "int", $timer, "int", 0)

AdlibRegister( "SpeakingClock", 1000)

While Sleep(100000000)
WEnd

Func Draw()
	_GDIPlus_GraphicsClear($hBackbuffer, 0xF0FFFFFF)

	_GDIPlus_GraphicsDrawLine($hBackbuffer, $cX - $cR, $cY, $cX - $cR + 35, $cY, $hPen1)
	_GDIPlus_GraphicsDrawLine($hBackbuffer, $cX + $cR, $cY, $cX + $cR - 35, $cY, $hPen1)
	_GDIPlus_GraphicsDrawLine($hBackbuffer, $cX, $cY - $cR, $cX, $cY - $cR + 35, $hPen1)
	_GDIPlus_GraphicsDrawLine($hBackbuffer, $cX, $cY + $cR, $cX, $cY + $cR - 35, $hPen1)
	_GDIPlus_GraphicsDrawEllipse($hBackbuffer, $cX - $cR, $cY - $cR, $radius, $radius, $hPen1)

	For $i = 0 To 11
		_GDIPlus_GraphicsDrawString($hBackbuffer, $i + 1, -$fs / 2 + $cX + Cos(-45 + $i * 29.7 * $deg) * $cR3, -$fs * 0.9 + $cY + Sin(-45 + $i * 29.7 * $deg) * $cR3, $font, $fs)
	Next
	If Int(StringLeft(_NowTime(4), 2) / 12) Then
		$tm = "PM"
	Else
		$tm = "AM"
	EndIf
	_GDIPlus_GraphicsDrawString($hBackbuffer, $tm,  -$tms * 1.1 + $cX, $tmh, $font, $tms)

	$x5 = $cX + Cos($std * $deg) * $cR5
	$y5 = $cY + Sin($std * $deg) * $cR5
	_GDIPlus_GraphicsDrawLine($hBackbuffer, $x5, $y5, $cX, $cY, $hPen2) ;hours

	$x3 = $cX + Cos($min * $deg) * $cR3
	$y3 = $cY + Sin($min * $deg) * $cR3
	_GDIPlus_GraphicsDrawLine($hBackbuffer, $x3, $y3, $cX, $cY, $hPen3) ;minutes

	$x1 = $cX + Cos($sek * $deg) * $cR1
	$y1 = $cY + Sin($sek * $deg) * $cR1
	$x2 = $cX + Cos(($sek + 180) * $deg) * $cR2
	$y2 = $cY + Sin(($sek + 180) * $deg) * $cR2
	_GDIPlus_GraphicsDrawLine($hBackbuffer, Floor($x1), Floor($y1), Floor($x2), Floor($y2), $hPen4) ;seconds

	_GDIPlus_GraphicsDrawEllipse($hBackbuffer, $cX - 3, $cY - 3, 6, 6, $hPen1)

	_GDIPlus_GraphicsDrawString($hBackbuffer, @HOUR & ":" & @MIN & ":" & @SEC, 0, 0)
	_GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, 0, 0, $iX, $iY)
	_WinAPI_RedrawWindow($hGUI)
EndFunc

Func SpeakingClock()
	If  $min = -90.00 And $speak_init And $SpeakingClock Then $oVoice.Speak("It is " & Mod(@HOUR, 12) & " " & $tm, 1)
EndFunc

Func WM_ERASEBKGND($hWnd, $Msg, $wParam, $lParam)
    Local $hGraphicsTemp = _GDIPlus_GraphicsCreateFromHDC($wParam)
    _GDIPlus_GraphicsDrawImageRect($hGraphicsTemp, $hBitmap, 0, 0, $iX, $iY)
    _GDIPlus_GraphicsDispose($hGraphicsTemp)
    Return True
EndFunc   ;==>_WM_ERASEBKGND

Func WM_SIZE($hWnd, $Msg, $wParam, $lParam)
	$iX = BitAND($lParam, 0x0000FFFF)
	$iY = BitShift(BitAND($lParam, 0xFFFF0000), 16)
;~ 	ConsoleWrite("x: " & $iX & ", y: " & $iY & @CRLF)
	_WinAPI_RedrawWindow($hGUI)
	Return "GUI_RUNDEFMSG"
EndFunc

Func WM_SIZING($hWnd, $iMsg, $wParam, $lParam)
    Local $sRect = DllStructCreate("Int[4]", $lParam)
    Local $left = DllStructGetData($sRect, 1, 1)
    Local $top = DllStructGetData($sRect, 1, 2)
    Local $right = DllStructGetData($sRect, 1, 3)
    Local $bottom = DllStructGetData($sRect, 1, 4)

    Switch $wParam ;drag side or corner
        Case 1, 2, 4, 7
            $newY = ($right - $left) * $ratio
            DllStructSetData($sRect, 1, DllStructGetData($sRect, 1, 2) + $newY, 4)
        Case Else
            $newX = ($bottom - $top) / $ratio
            DllStructSetData($sRect, 1, DllStructGetData($sRect, 1, 1) + $newX, 3)
	EndSwitch
    Return "GUI_RUNDEFMSG"
EndFunc   ;==>WM_SIZING

Func WM_GETMINMAXINFO($hWnd, $Msg, $wParam, $lParam)
    Local $minmaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam)
    DllStructSetData($minmaxinfo, 7, $minSize) ; min X
    DllStructSetData($minmaxinfo, 8, $minSize) ; min Y
    DllStructSetData($minmaxinfo, 9, $maxSize) ; max X
    DllStructSetData($minmaxinfo, 10, $maxSize) ; max Y
    Return "GUI_RUNDEFMSG"
EndFunc   ;==>WM_GETMINMAXINFO

Func Ticker()
	$sek = @SEC * 6 - 90
	$min = @MIN * 6 + (@SEC * 0.10) - 90
	$std = @HOUR * 30 + (@MIN * 0.50) - 90
EndFunc

Func _Exit()
	AdlibUnRegister("Ticker")
	AdlibUnRegister("SpeakingClock")
	$oVoice = 0
	GUIRegisterMsg($WM_TIMER, "")
	GUIRegisterMsg($WM_GETMINMAXINFO, "")
	GUIRegisterMsg($WM_SIZE, "")
	GUIRegisterMsg($WM_ERASEBKGND, "")
	GUIRegisterMsg($WM_SIZING, "")

	; Clean up GDI+ resources
	_GDIPlus_CustomLineCapDispose($hCustomLineCap)
	_GDIPlus_PathDispose($hPath)
	_GDIPlus_PenDispose($hPen1)
	_GDIPlus_PenDispose($hPen2)
	_GDIPlus_PenDispose($hPen3)
	_GDIPlus_PenDispose($hPen4)
	_GDIPlus_BitmapDispose($hBitmap)
	_GDIPlus_GraphicsDispose($hBackbuffer)
	_GDIPlus_GraphicsDispose($hGraphics)

	; Uninitialize GDI+
	_GDIPlus_Shutdown()
	GUIDelete($hGUI)
	Exit
EndFunc

Func _GDIPlus_PathCreate($iFillMode = 0)
	Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreatePath", "int", $iFillMode, "int*", 0)
	If @error Then Return SetError(@error, @extended, 0)
	Return $aResult[2]
EndFunc   ;==>_GDIPlus_PathCreate

Func _GDIPlus_PathAddLines($hPath, $aPoints)
	Local $iI, $iCount, $pPoints, $tPoints, $aResult
	$iCount = $aPoints[0][0]
	$tPoints = DllStructCreate("float[" & $iCount * 2 & "]")
	$pPoints = DllStructGetPtr($tPoints)
	For $iI = 1 To $iCount
		DllStructSetData($tPoints, 1, $aPoints[$iI][0], (($iI - 1) * 2) + 1)
		DllStructSetData($tPoints, 1, $aPoints[$iI][1], (($iI - 1) * 2) + 2)
	Next
	$aResult = DllCall($ghGDIPDll, "uint", "GdipAddPathLine2", "hwnd", $hPath, "ptr", $pPoints, "int", $iCount)
	If @error Then Return SetError(@error, @extended, False)
	Return $aResult[0] = 0
EndFunc   ;==>_GDIPlus_PathAddLines

Func _GDIPlus_PathDispose($hPath)
	Local $aResult = DllCall($ghGDIPDll, "uint", "GdipDeletePath", "hwnd", $hPath)
	If @error Then Return SetError(@error, @extended, False)
	Return $aResult[0] = 0
EndFunc   ;==>_GDIPlus_PathDispose

Func _GDIPlus_CustomLineCapCreate($hPathFill, $hPathStroke, $iLineCap = 0, $nBaseInset = 0)
	Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateCustomLineCap", "hwnd", $hPathFill, "hwnd", $hPathStroke, "int", $iLineCap, "float", $nBaseInset, "int*", 0)
	If @error Then Return SetError(@error, @extended, 0)
	Return $aResult[5]
EndFunc   ;==>_GDIPlus_CustomLineCapCreate

Func _GDIPlus_CustomLineCapSetStrokeCaps($hCustomLineCap, $iStartCap, $iEndCap)
	Local $aResult = DllCall($ghGDIPDll, "uint", "GdipSetCustomLineCapStrokeCaps", "hwnd", $hCustomLineCap, "int", $iStartCap, "int", $iEndCap)
	If @error Then Return SetError(@error, @extended, False)
	Return $aResult[0] = 0
EndFunc   ;==>_GDIPlus_CustomLineCapSetStrokeCaps

Func _GDIPlus_CustomLineCapGetStrokeCaps($hCustomLineCap)
	Local $aCaps[2], $aResult
	$aResult = DllCall($ghGDIPDll, "uint", "GdipGetCustomLineCapStrokeCaps", "hwnd", $hCustomLineCap, "int*", 0, "int*", 0)
	If @error Then Return SetError(@error, @extended, -1)
	If $aResult[0] Then Return -1
	$aCaps[0] = $aResult[2]
	$aCaps[1] = $aResult[3]
	Return $aCaps
EndFunc   ;==>_GDIPlus_CustomLineCapGetStrokeCap

Func _GDIPlus_PenSetLineCap($hPen, $iStartCap, $iEndCap, $iDashCap)
	Local $aResult = DllCall($ghGDIPDll, "uint", "GdipSetPenLineCap197819", "hwnd", $hPen, "int", $iStartCap, "int", $iEndCap, "int", $iDashCap)
	If @error Then Return SetError(@error, @extended, False)
	Return $aResult[0] = 0
EndFunc   ;==>_GDIPlus_PenSetLineCap
