Add an Animated Eye Clock to Your Windows Desktop Using AutoIt
An animated eye clock is a fun desktop widget that shows the time while a stylized “eye” follows the cursor or blinks on the hour. Below is a step-by-step guide to build a simple, lightweight animated eye clock in AutoIt. It includes creating the GUI, drawing the eye graphics, updating time, and adding basic animation like pupil tracking and blinking.
What you’ll get
- A borderless, always-on-top desktop clock showing current time.
- A circular eye graphic with a movable pupil that follows the mouse.
- Hourly blink animation and smooth updates.
Requirements
- AutoIt v3 (latest stable).
- AutoIt Window Info tool (optional, for positioning).
- A plain text editor (SciTE recommended).
File structure
- EyeClock.au3 — main script
- Assets (optional) — any images if you prefer bitmap eyes (not required for drawing with GDI+)
Full script (EyeClock.au3)
autoit
; EyeClock.au3; Simple animated eye clock for Windows using AutoIt + GDI+; Requires AutoIt3 (v3.x)
#RequireAdmin ; optional if you need special permissions#include #include #include #include
Global Const \(WIDTH = 220</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">Global Const \)HEIGHT = 120Global Const \(EYE_RADIUS = 30</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">Global Const \)PUPIL_RADIUS = 9Global Const \(EYE_OFFSET_X = 60</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">Global Const \)EYE_OFFSET_Y = 50
; Start GDI+_GDIPlus_Startup()
; Create transparent, borderless GUI\(hGUI = GUICreate("", \)WIDTH, \(HEIGHT, -1, -1, BitOR(\)WS_POPUP, \(WS_EX_TOPMOST))</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">GUISetBkColor(0x000000, \)hGUI); Make window layered and transparent for click-through background (keeps controls clickable)_WinAPI_SetWindowLong(\(hGUI, \)GWL_EXSTYLE, BitOR(_WinAPI_GetWindowLong(\(hGUI, \)GWL_EXSTYLE), \(WS_EX_LAYERED))</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">_WinAPI_SetLayeredWindowAttributes(\)hGUI, 0x000000, 255, \(LWA_COLORKEY)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"> </span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">GUISetState(@SW_SHOW, \)hGUI)
; Create GDI+ graphics surface\(hImage = _GDIPlus_BitmapCreateFromScan0(\)WIDTH, \(HEIGHT)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">\)hGraphics = _GDIPlus_ImageGetGraphicsContext(\(hImage)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"> </span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">; Font for time</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">Local \)hFont = _GDIPlus_FontCreate(“Segoe UI”, 18, \(GDIP_FONTSTYLE_BOLD)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"> </span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">; Blink control</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">Global \)g_blinkTimer = TimerInit()Global \(g_blinkState = False</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]">Global \)g_lastBlink = 0
; Main loopWhile 1; Clear _GDIPlus_GraphicsClear(\(hGraphics, 0x00FFFFFF)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"> </span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> ; Draw clock background</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> _GDIPlus_GraphicsFillEllipse(\)hGraphics, _MakeBrush(0xFFEFEFEF), 10, 10, 80, 80) ; left eye bg _GDIPlus_GraphicsFillEllipse(\(hGraphics, _MakeBrush(0xFFEFEFEF), 130, 10, 80, 80) ; right eye bg</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"> </span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> ; Calculate pupil positions based on mouse</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> Local \)mousePos = MouseGetPos() Local \(winPos = WinGetPos("")</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> ; If multiple windows, we need our GUI position specifically</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> \)winPos = WinGetPos(“[HANDLE:” & GUICtrlGetHandle(\(hGUI) & "]")</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> Local \)leftEyeCenterX = \(winPos[0] + 10 + \)EYE_RADIUS Local \(leftEyeCenterY = \)winPos[1] + 10 + \(EYE_RADIUS</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> Local \)rightEyeCenterX = \(winPos[0] + 130 + \)EYE_RADIUS Local \(rightEyeCenterY = \)winPos[1] + 10 + \(EYE_RADIUS</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"> </span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> Local \)lp = _CalcPupil(\(leftEyeCenterX, \)leftEyeCenterY, \(mousePos[0], \)mousePos[1], \(EYE_RADIUS - \)PUPIL_RADIUS - 4) Local \(rp = _CalcPupil(\)rightEyeCenterX, \(rightEyeCenterY, \)mousePos[0], \(mousePos[1], \)EYE_RADIUS - \(PUPIL_RADIUS - 4)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"> </span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> ; Blink every ~10-18 minutes randomly or on the hour</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> If Mod(@MIN, 60) = 0 And @SEC < 2 And \)g_lastBlink <> @MIN Then \(g_blinkState = True</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> \)g_lastBlink = @MIN \(g_blinkTimer = TimerInit()</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> ElseIf TimerDiff(\)g_blinkTimer) > 120 And \(g_blinkState Then</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> \)g_blinkState = False ElseIf Not \(g_blinkState And Random(0, 1, 1) < 0.005 Then ; occasional blink</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> \)g_blinkState = True \(g_blinkTimer = TimerInit()</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> EndIf</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"> </span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> ; Draw eyes or blink (simple eyelid rectangle)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> If \)g_blinkState Then ; Draw closed eyelids _GDIPlus_GraphicsFillRectangle(\(hGraphics, _MakeBrush(0xFFDDDDDD), 10, 10 + \)EYE_RADIUS - 8, 80, 16) _GDIPlus_GraphicsFillRectangle(\(hGraphics, _MakeBrush(0xFFDDDDDD), 130, 10 + \)EYE_RADIUS - 8, 80, 16) Else ; Draw irises _GDIPlus_GraphicsFillEllipse(\(hGraphics, _MakeBrush(0xFF6AA2FF), 10 + (\)EYE_RADIUS - 18), 10 + (\(EYE_RADIUS - 18), 36, 36)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> _GDIPlus_GraphicsFillEllipse(\)hGraphics, _MakeBrush(0xFF6AA2FF), 130 + (\(EYE_RADIUS - 18), 10 + (\)EYE_RADIUS - 18), 36, 36)
; Draw pupils _GDIPlus_GraphicsFillEllipse(\(hGraphics, _MakeBrush(0xFF000000), \)lp[0] - \(PUPIL_RADIUS, \)lp[1] - \(PUPIL_RADIUS, \)PUPIL_RADIUS*2, \(PUPIL_RADIUS*2)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> _GDIPlus_GraphicsFillEllipse(\)hGraphics, _MakeBrush(0xFF000000), \(rp[0] - \)PUPIL_RADIUS, \(rp[1] - \)PUPIL_RADIUS, \(PUPIL_RADIUS*2, \)PUPIL_RADIUS*2)
; Highlights _GDIPlus_GraphicsFillEllipse(\(hGraphics, _MakeBrush(0xFFFFFFFF), \)lp[0] - 4, \(lp[1] - 6, 6, 6)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> _GDIPlus_GraphicsFillEllipse(\)hGraphics, _MakeBrush(0xFFFFFFFF), \(rp[0] - 4, \)rp[1] - 6, 6, 6) EndIf
; Draw time text Local \(timeStr = StringFormat("%02d:%02d:%02d", @HOUR, @MIN, @SEC)</span></span><span class="block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-[13px] before:text-right before:text-muted-foreground/50 before:font-mono before:select-none"><span class="text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]"> _GDIPlus_GraphicsDrawString(\)hGraphics, \(timeStr, \)hFont, 80, 70, _MakeBrush(0xFF000000))
; Render to GUI
Leave a Reply