; Coded by InunoTaishou ; Credits to UEZ for the code to draw a heart #include #include #include #include #pragma compile(Icon, "heart.ico") Opt("MustDeclareVars", 1) Opt("GUICloseOnEsc", 1) Opt("TrayIconHide", 1) _GDIPlus_Startup() Global Const $HAPPY_VALENTINES = "Happy Valentine's Day AutoIT" ; maximum hearts to be drawn Global Const $MAX_HEART_COUNT = 50 ; bounding rectangle that encloses the above string, width and height Global Const $VALENTINE_STRING_WIDTH = 400 Global Const $VALENTINE_STRING_HEIGHT = 150 Global Const $MIN_HEART_SIZE = 50 Global Const $MAX_HEART_SIZE = 250 Global Const $RECT_HAPPY_VALENTINES[4] = [(@DesktopWidth / 2) - ($VALENTINE_STRING_WIDTH / 2), (@DesktopHeight / 2) - ($VALENTINE_STRING_HEIGHT / 2), $VALENTINE_STRING_WIDTH, $VALENTINE_STRING_HEIGHT] ; x, y, width, height Global Const $MIN_TIMEOUT = 3000 Global Const $MAX_TIMEOUT = 7000 Global Const $MIN_VERTICAL_SPEED = 2 Global Const $MAX_VERTICAL_SPEED = 5 Global Const $MIN_HORIZONTAL_OFFSET = 100 Global Const $MAX_HORIZONTAL_OFFSET = 175 Global Const $PNG_HEART_PATH = @TempDir & "\heart.png" Global Const $HWND_PEN = _GDIPlus_PenCreate(0, 1) Global Const $HWND_FONT_FAMILY = _GDIPlus_FontFamilyCreate("Segoe UI") Global Const $HWND_FONT_VALENTINE = _GDIPlus_FontCreate($HWND_FONT_FAMILY, 32) Global Const $RECT_VALENTINE = _GDIPlus_RectFCreate($RECT_HAPPY_VALENTINES[0], $RECT_HAPPY_VALENTINES[1], $RECT_HAPPY_VALENTINES[2], $RECT_HAPPY_VALENTINES[3]) Global Const $RECT_FPS = _GDIPlus_RectFCreate(0, 0, 50, 16) Global Const $HWND_FONT_FPS = _GDIPlus_FontCreate($HWND_FONT_FAMILY, 8.5) Global Const $HWND_STRING_FORMAT_VALENTINE = _GDIPlus_StringFormatCreate() Global Const $HWND_STRING_FORMAT_FPS = _GDIPlus_StringFormatCreate() Global Const $HWND_VALENTINE_TEXT_BRUSH = _GDIPlus_BrushCreateSolid(0xFFFF0000) Global Const $HWND_BK_BRUSH = _GDIPlus_BrushCreateSolid(0xFF1A1A1A) Global Const $HWND_FPS_BRUSH = _GDIPlus_BrushCreateSolid(0xFFFFFFFF) Global Const $pi = ACos(-1) Global Const $dy = 30 Global $dist, $p, $l, $r, $col Global $heart_buffer[$MAX_HEART_COUNT][12] Global $frmMain = GUICreate("<3", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST)) Global $fps_counter = 0 Global $fps = 0 Global $hWnd_graphic = _GDIPlus_GraphicsCreateFromHWND($frmMain) Global $hWnd_bitmap = _GDIPlus_BitmapCreateFromGraphics(@DesktopWidth, @DesktopHeight, $hWnd_graphic) Global $hWnd_backbuffer = _GDIPlus_ImageGetGraphicsContext($hWnd_bitmap) GDIPValentinesDay() Func GDIPValentinesDay() Local Const $hWnd_heart_bitmap = CreateHeartBitmap($MAX_HEART_SIZE, ($MAX_HEART_SIZE - 1), ($MAX_HEART_SIZE / 2)) ; center text _GDIPlus_StringFormatSetAlign($HWND_STRING_FORMAT_VALENTINE, 1) _GDIPlus_StringFormatSetLineAlign($HWND_STRING_FORMAT_VALENTINE, 1) ; set smoothing _GDIPlus_GraphicsSetSmoothingMode($hWnd_backbuffer, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsSetSmoothingMode($hWnd_graphic, $GDIP_SMOOTHINGMODE_HIGHQUALITY) GUISetBkColor(0x000000, $frmMain) _WinAPI_SetLayeredWindowAttributes($frmMain, 0x000000, 255) GUISetState(@SW_SHOW, $frmMain) SetHeartsMap() AdlibRegister("CalculateFps", 1000) Do _GDIPlus_GraphicsClear($hWnd_backbuffer, 0xFF000000) For $i = 0 To $MAX_HEART_COUNT - 1 ; if there is a timer If ($heart_buffer[$i][4] <> -1) Then ; if the timer has reached the timeout If (TimerDiff($heart_buffer[$i][5]) > $heart_buffer[$i][4]) Then ; shrink the heart $heart_buffer[$i][2] -= 2 $heart_buffer[$i][3] -= 2 EndIf EndIf ; if the heart has a horizontal move If ($heart_buffer[$i][7]) Then ; if the number of pixels moved in the x position is greater than the max pixels to move horizontally If (Abs($heart_buffer[$i][10]) > Abs($heart_buffer[$i][9])) Then If ($heart_buffer[$i][11] > 15) Then ; change direction $heart_buffer[$i][8] *= -1 ; reset the jerk counter $heart_buffer[$i][11] = 0 Else $heart_buffer[$i][11] += 1 EndIf EndIf ; adjust the x offset $heart_buffer[$i][0] += $heart_buffer[$i][8] ; adjust how many pixels the heart has moved in that direction $heart_buffer[$i][10] += $heart_buffer[$i][8] EndIf ; if the y position of the heart is <= 0 or the heart width <= 2, reset that heart If ($heart_buffer[$i][1] <= ($heart_buffer[$i][2] * -1) Or $heart_buffer[$i][2] <= 2) Then SetHeartStats($i) _GDIPlus_GraphicsDrawImageRect($hWnd_backbuffer, $hWnd_heart_bitmap, $heart_buffer[$i][0], $heart_buffer[$i][1], $heart_buffer[$i][2], $heart_buffer[$i][3]) ; adjust y coordinate of heart $heart_buffer[$i][1] -= $heart_buffer[$i][6] Next _GDIPlus_GraphicsFillRect($hWnd_backbuffer, $RECT_HAPPY_VALENTINES[0], $RECT_HAPPY_VALENTINES[1], $RECT_HAPPY_VALENTINES[2], $RECT_HAPPY_VALENTINES[3], $HWND_BK_BRUSH) _GDIPlus_GraphicsDrawStringEx($hWnd_backbuffer, $HAPPY_VALENTINES, $HWND_FONT_VALENTINE, $RECT_VALENTINE, $HWND_STRING_FORMAT_VALENTINE, $HWND_VALENTINE_TEXT_BRUSH) _GDIPlus_GraphicsFillRect($hWnd_backbuffer, 0, 0, 50, 16, $HWND_BK_BRUSH) _GDIPlus_GraphicsDrawStringEx($hWnd_backbuffer, "FPS: " & $fps_counter, $HWND_FONT_FPS, $RECT_FPS, $HWND_STRING_FORMAT_FPS, $HWND_FPS_BRUSH) _GDIPlus_GraphicsDrawImage($hWnd_graphic, $hWnd_bitmap, 0, 0) $fps += 1 Sleep(10) Until (GUIGetMsg() = $GUI_EVENT_CLOSE) AdlibUnRegister("CalculateFps") _GDIPlus_PenDispose($HWND_PEN) _GDIPlus_GraphicsDispose($hWnd_graphic) _GDIPlus_BitmapDispose($hWnd_bitmap) _GDIPlus_BitmapDispose($hWnd_heart_bitmap) _GDIPlus_FontFamilyDispose($HWND_FONT_FAMILY) _GDIPlus_FontDispose($HWND_FONT_VALENTINE) _GDIPlus_StringFormatDispose($HWND_STRING_FORMAT_VALENTINE) _GDIPlus_BrushDispose($HWND_VALENTINE_TEXT_BRUSH) _GDIPlus_BrushDispose($HWND_BK_BRUSH) _GDIPlus_FontDispose($HWND_FONT_FPS) _GDIPlus_StringFormatDispose($HWND_STRING_FORMAT_FPS) _GDIPlus_BrushDispose($HWND_FPS_BRUSH) _GDIPlus_Shutdown() GUIDelete($frmMain) Return 0 EndFunc ;==>GDIPValentinesDay Func CalculateFps() $fps_counter = $fps $fps = 0 EndFunc ;==>CalculateFps Func SetHeartsMap() For $i = 0 To $MAX_HEART_COUNT - 1 SetHeartStats($i) Next EndFunc ;==>SetHeartsMap Func SetHeartStats(Const ByRef $iIndex) ; determine horizontal direction to move Local Const $multiply_by = (Random(0, 1, 1) ? 1 : -1) Local $valid_position = False Local $y_offset = 0 ; width of heart $heart_buffer[$iIndex][2] = Ceiling(Random($MIN_HEART_SIZE, $MAX_HEART_SIZE, 1) / 10) * 10 ; height of heart $heart_buffer[$iIndex][3] = $heart_buffer[$iIndex][2] - 1 Do ; x position of heart $heart_buffer[$iIndex][0] = Random(0, @DesktopWidth, 1) ; y position of heart $heart_buffer[$iIndex][1] = Random(@DesktopHeight - $MIN_HEART_SIZE - $y_offset, @DesktopHeight, 1) For $i = 0 To $MAX_HEART_COUNT - 1 If ($i = $iIndex) Then ContinueLoop ; make sure the heart doesn't start in the same spot as another heart If (_WinAPI_PtInRectEx($heart_buffer[$iIndex][0], $heart_buffer[$iIndex][1], $heart_buffer[$i][0], $heart_buffer[$i][1], $heart_buffer[$i][0] + $heart_buffer[$i][2], $heart_buffer[$i][1] + $heart_buffer[$i][3])) Then $valid_position = False $y_offset += 5 ExitLoop Else $valid_position = True EndIf Next Until ($valid_position) If (Random(0, 3, 1) = False) Then ; add timeout for some hearts $heart_buffer[$iIndex][4] = Random($MIN_TIMEOUT, $MAX_TIMEOUT, 1) ; init timer for that heart $heart_buffer[$iIndex][5] = TimerInit() Else $heart_buffer[$iIndex][4] = -1 $heart_buffer[$iIndex][5] = 0 EndIf ; set vertical move speed $heart_buffer[$iIndex][6] = Random($MIN_VERTICAL_SPEED, $MAX_VERTICAL_SPEED, 1) ;If (Random(0, 3, 1) = False) Then If (True) Then ; horizontal moving is true $heart_buffer[$iIndex][7] = True ; set horizontal move speed $heart_buffer[$iIndex][8] = Random($MIN_VERTICAL_SPEED / 2, $MAX_VERTICAL_SPEED / 2, 1) * $multiply_by ; set the max pixels to move horizontally $heart_buffer[$iIndex][9] = Random($MIN_HORIZONTAL_OFFSET, $MAX_HORIZONTAL_OFFSET, 1) * $multiply_by ; set the pixels the heart has moved in this direction $heart_buffer[$iIndex][10] = 0 ; set the counter to 0, this controls how long to wait before adjusting direction once it's reached the max horizontal offset. (makes the heart not jerk left/right) $heart_buffer[$iIndex][11] = 0 Else ; horizontal moving is false $heart_buffer[$iIndex][7] = False $heart_buffer[$iIndex][8] = 0 $heart_buffer[$iIndex][9] = 0 $heart_buffer[$iIndex][10] = 0 $heart_buffer[$iIndex][11] = 0 EndIf EndFunc ;==>SetHeartStats Func CreateHeartBitmap(Const ByRef $iW, Const ByRef $iH, Const ByRef $iRadius) Local $hWnd_heart_graphic = _GDIPlus_GraphicsCreateFromHWND($frmMain) Local $hWnd_heart_bitmap = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hWnd_heart_graphic) Local $hWnd_heart_buffer = _GDIPlus_ImageGetGraphicsContext($hWnd_heart_bitmap) Local $percent = 0 If (Not FileExists(@TempDir & "\heart.png")) Then ToolTip("Drawing heart, please wait ... 0% complete") _GDIPlus_GraphicsSetSmoothingMode($hWnd_heart_buffer, 2) _GDIPlus_GraphicsClear($hWnd_heart_buffer, 0x00000000) For $y = 1 To $iH For $x = 1 To $iW $dist = Sqrt((($iW / 2) - $x) ^ 2 + (($iH / 2) - $y) ^ 2) $p = ATan2(($iW / 2) - $x, ($iH / 2) - $y) $l = Abs($p) / $pi $r = (13 * $l - 22 * $l ^ 2 + 10 * $l ^ 3) / (6 - 5 * $l) * $iRadius If $dist <= $r Then $col = "0xFFFF0000" Else $col = "0x00000000" EndIf _GDIPlus_PenSetColor($HWND_PEN, $col) _GDIPlus_GraphicsDrawRect($hWnd_heart_buffer, $x, $y - $dy, 1, 1, $HWND_PEN) Next $percent = Round((($y * $iW) / ($iH * $iW)) * 100, 0) ToolTip("Drawing heart, please wait ..." & @CRLF & @TAB & @TAB & $percent & "% complete" & @CRLF & "[" & StringPercent($percent) & "]") Next ToolTip("") _GDIPlus_ImageSaveToFile($hWnd_heart_bitmap, $PNG_HEART_PATH) Else $hWnd_heart_bitmap = _GDIPlus_ImageLoadFromFile($PNG_HEART_PATH) ; if the saved image is not the proper size, remake it If (_GDIPlus_ImageGetWidth($hWnd_heart_bitmap) <> $MAX_HEART_SIZE) Then _GDIPlus_BitmapDispose($hWnd_heart_bitmap) _GDIPlus_GraphicsDispose($hWnd_heart_graphic) Do FileDelete($PNG_HEART_PATH) Until (Not FileExists($PNG_HEART_PATH)) Return CreateHeartBitmap($iW, $iH, $iRadius) EndIf EndIf _GDIPlus_GraphicsDispose($hWnd_heart_graphic) Return $hWnd_heart_bitmap EndFunc ;==>CreateHeartBitmap Func StringPercent(Const ByRef $iPercent) Local $string_return = "" For $i = 0 To $iPercent $string_return &= "|" Next For $i = $iPercent To 100 $string_return &= " " Next Return $string_return EndFunc ;==>StringPercent Func ATan2($y, $x) Return (2 * ATan($y / ($x + Sqrt($x * $x + $y * $y)))) EndFunc ;==>ATan2