Notice
Recent Posts
Recent Comments
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Directory Opus
- Alchemy CATALYST 2023
- 한글패치
- 지역화
- 백신
- 파일 탐색기
- 레시피
- 안다르
- 국민연금
- 범용 태그 편집기
- 건강
- 반디집
- 이녁하늘
- 디스크샷
- 운동
- Soluling
- Alchemy CATALYST 2021
- n번방 자료실
- 한글2024
- 한글 패치
- ANDAR
- 한글화
- 이녁 하늘
- 티스토리챌린지
- 여행
- 파일관리자
- v3
- 오블완
- 파솔로 2022
- 탐색기
Archives
- Today
- Total
이녁 하늘 아래
소스 / Clock.au3 본문
Clock.au3

; https://www.autoitscript.com/forum/topic/213036-%F0%9F%95%91-analog-clock/
;----------------------------------------------------------------------------------------
; Title...........: Analog_Clock.au3
; Description.....: Analog clock GUI with alarm functionality.
; AutoIt Version..: 3.3.16.1 Author: ioa747 Script Version: 0.12
; Note............: Testet in Win10 22H2
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Math.au3>
#include <Array.au3>
#include <GUIConstantsEx.au3>
#include <TrayConstants.au3>
#include <Misc.au3>
#include <Timers.au3>
Opt("TrayMenuMode", 3) ; 0=append, 1=no default menu, 2=no automatic check, 4=menuitemID not return
; Global Constants
Global Const $AC_SRC_ALPHA = 0x01
Global Const $GDIP_TEXTRENDERINGHINT_CLEARTYPEGRIDFIT = 5
Global Const $GDIP_STRINGFORMAT_ALIGNMENT_CENTER = 1
Global Const $GDIP_STRINGFORMAT_LINEALIGNMENT_CENTER = 1
; Global Variables
Global $hGUIClock
Global $hImageBuffer, $hGraphicBuffer
Global $hClockImage = 0
Global $hPenSeconds, $hPenMinutes, $hPenHours, $hBrushCenter
Global $iClockWidth = 600, $iClockHeight = 600
Global $mClock = _GetClockSetting(StringTrimRight(@ScriptFullPath, 4) & ".ini")
_GDIPlus_Startup()
; Try to load a clock background image
_GetClockImage($mClock.Image)
; Start the Clock GUI
_CreateClock($mClock.Width, $mClock.X, $mClock.Y)
Exit ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Try to load the clock background image
Func _GetClockImage($sImagePath = Default)
; The Default clock background image
If $sImagePath = Default Or $sImagePath = "Default" Then $sImagePath = StringTrimRight(@ScriptFullPath, 4) & ".png"
If Not FileExists($sImagePath) Then
ConsoleWrite("WARNING: ClockImage not found or could not be loaded initially. fallback to Default" & @CRLF)
; Set $sImagePath to Default
$sImagePath = StringTrimRight(@ScriptFullPath, 4) & ".png"
EndIf
; If there isn't one, make one.
If Not FileExists($sImagePath) Then
ConsoleWrite("WARNING: Default Image not found or could not be loaded initially. Generating new image..." & @CRLF)
Local $bOk = _CreateAndSaveClockImage($iClockWidth, $sImagePath)
If $bOk Then
ConsoleWrite("INFO: Default Image generated successfully. Attempting to load it now." & @CRLF)
Else
ConsoleWrite("ERROR: Failed to generate Default Image Will go to exit." & @CRLF)
Exit
EndIf
EndIf
$hClockImage = _GDIPlus_ImageLoadFromFile($sImagePath)
; Check if loaded image is a valid pointer and file has content
If IsPtr($hClockImage) And FileGetSize($sImagePath) > 0 Then
ConsoleWrite("INFO: Loaded ClockImage." & @CRLF)
Else
ConsoleWrite("ERROR: Failed to Loaded the ClockImage. Will go to exit." & @CRLF)
Exit
EndIf
EndFunc ;==>_GetClockImage
; Clock GUI - Initialization and Main Loop
Func _CreateClock($iWidth, $iX = -1, $iY = -1)
; Tray Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Local $idMove = TrayCreateItem("Move")
Local $idAlarmActive = TrayCreateItem("Alarm Enable/Disable")
TrayItemSetState($idAlarmActive, ($mClock.Alarm = "1" ? $TRAY_CHECKED : $TRAY_UNCHECKED))
Local $iSettings = TrayCreateMenu("Settings")
Local $idSetAlarm = TrayCreateItem("Alarm Setting", $iSettings)
Local $idSetColors = TrayCreateItem("Colors Setting", $iSettings)
Local $idIniFile = TrayCreateItem("Ini file", $iSettings)
Local $idRestart = TrayCreateItem("Restart", $iSettings)
TrayCreateItem("") ; separator -----------------------
Local $idClose = TrayCreateItem("Close")
TraySetClick($TRAY_CLICK_SECONDARYUP)
TraySetIcon("mmcndmgr.dll", -15)
TraySetToolTip("Analog Clock")
TraySetState($TRAY_ICONSTATE_SHOW) ; Show the tray menu.
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Local $hDLL = DllOpen("user32.dll") ; for _IsPressed
$iClockWidth = $iWidth
$iClockHeight = $iWidth
; The clock GUI
$hGUIClock = GUICreate("Analog Clock", $iClockWidth, $iClockHeight, $iX, $iY, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW))
Local $idMouseLab = GUICtrlCreateLabel("", $iWidth / 2 - 5, $iWidth / 2 - 5, 10, 10)
GUISetState(@SW_SHOW)
$hImageBuffer = _GDIPlus_BitmapCreateFromScan0($iClockWidth, $iClockHeight)
$hGraphicBuffer = _GDIPlus_ImageGetGraphicsContext($hImageBuffer)
_GDIPlus_GraphicsSetSmoothingMode($hGraphicBuffer, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
; Colors from inifile RGB to ARGB
Local $sColorSeconds = "0xFF" & StringTrimLeft($mClock.ColorSeconds, 2)
Local $sColorMinutes = "0xFF" & StringTrimLeft($mClock.ColorMinutes, 2)
Local $sColorHours = "0xFF" & StringTrimLeft($mClock.ColorHours, 2)
Local $sColorCenter = "0xFF" & StringTrimLeft($mClock.ColorCenter, 2)
; hands Width
Local $iWSeconds = ($iWidth * 0.005 < 2 ? 2 : $iWidth * 0.005)
Local $iWMinutes = ($iWidth * 0.015 < 4 ? 4 : $iWidth * 0.015)
Local $iWHours = ($iWidth * 0.020 < 6 ? 6 : $iWidth * 0.020)
; Initialize pens and brush for drawing hands and center circle
$hPenSeconds = _GDIPlus_PenCreate($sColorSeconds, $iWSeconds) ; 0xFFFF0000
$hPenMinutes = _GDIPlus_PenCreate($sColorMinutes, $iWMinutes) ; 0xFF40C880
$hPenHours = _GDIPlus_PenCreate($sColorHours, $iWHours) ; 0xFF0080C0
$hBrushCenter = _GDIPlus_BrushCreateSolid($sColorCenter) ; 0xFF000000
; SetTimer so it doesn't freeze with the tray menu
_Timer_SetTimer($hGUIClock, 250, "_RedrawClock")
Local $bRestart, $aMpos, $iCnt = 0, $Tick = -1
;********************************************
While 1
; Check Alarm
If $Tick <> @MIN Then
$Tick = @MIN
_CheckAlarm()
_ActivityTimeout($mClock.ActivityTimeout)
EndIf
; GUI Msg $idMouseLab
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
ExitLoop
Case $GUI_EVENT_PRIMARYDOWN
; long press Left mouse button in bullet, to move the clock
Local $a = GUIGetCursorInfo()
If $a[4] = $idMouseLab Then
While _IsPressed("01", $hDLL) ; 01 Left mouse button
$iCnt += 1
If $iCnt > 60 Then
$aMpos = MouseGetPos()
WinMove($hGUIClock, '', $aMpos[0] - $iWidth / 2, $aMpos[1] - $iWidth / 2)
ToolTip("Move it", $aMpos[0] + 30, $aMpos[1] - 10)
EndIf
Sleep(10)
WEnd
If $iCnt > 60 Then
ToolTip("")
$mClock.X = $aMpos[0] - $iWidth / 2
$mClock.Y = $aMpos[1] - $iWidth / 2
IniWrite($mClock.IniFile, "ClockSetting", "X", $mClock.X)
IniWrite($mClock.IniFile, "ClockSetting", "Y", $mClock.Y)
EndIf
$iCnt = 0
EndIf
EndSwitch
; Tray Msg
Switch TrayGetMsg()
Case $idClose
ExitLoop
Case $idMove ; move the clock
WinActivate($hGUIClock)
While 1
$aMpos = MouseGetPos()
WinMove($hGUIClock, '', $aMpos[0] - $iWidth / 2, $aMpos[1] - $iWidth / 2)
ToolTip("click to drop it", $aMpos[0] + 30, $aMpos[1] - 10)
If _IsPressed("01", $hDLL) Then ExitLoop ; 01 Left mouse button
Sleep(10)
WEnd
ToolTip("")
$mClock.X = $aMpos[0] - $iWidth / 2
$mClock.Y = $aMpos[1] - $iWidth / 2
IniWrite($mClock.IniFile, "ClockSetting", "X", $mClock.X)
IniWrite($mClock.IniFile, "ClockSetting", "Y", $mClock.Y)
Case $idAlarmActive ; Alarm Enable/Disable
If BitAND(TrayItemGetState($idAlarmActive), $TRAY_CHECKED) Then ; If $TRAY_CHECKED
TrayItemSetState($idAlarmActive, $TRAY_UNCHECKED)
IniWrite($mClock.IniFile, "ClockSetting", "Alarm", "0")
$mClock.Alarm = "0"
Else ; If $TRAY_UNCHECKED
TrayItemSetState($idAlarmActive, $TRAY_CHECKED)
IniWrite($mClock.IniFile, "ClockSetting", "Alarm", "1")
$mClock.Alarm = "1"
EndIf
Case $idSetAlarm ; Alarm Setting
_SetAlarm()
Case $idSetColors ; Colors Setting
_SetColors()
Case $idIniFile ; Ini File (open ini file)
ShellExecute($mClock.IniFile)
Case $idRestart ; Restart the clock
$bRestart = True
ExitLoop
Case $TRAY_EVENT_PRIMARYDOUBLE ; double click activate clock
WinActivate($hGUIClock)
EndSwitch
WEnd
;********************************************
; Clean up resources
_Timer_KillAllTimers($hGUIClock)
_GDIPlus_PenDispose($hPenSeconds)
_GDIPlus_PenDispose($hPenMinutes)
_GDIPlus_PenDispose($hPenHours)
_GDIPlus_BrushDispose($hBrushCenter)
_GDIPlus_GraphicsDispose($hGraphicBuffer)
_GDIPlus_ImageDispose($hImageBuffer)
_GDIPlus_ImageDispose($hClockImage)
_GDIPlus_Shutdown()
DllClose($hDLL)
GUIDelete($hGUIClock)
If $bRestart Then
Local $Cmd = StringRight(@ScriptFullPath, 4) = ".exe" ? '"' & @ScriptFullPath & '"' : '"' & @AutoItExe & '" "' & @ScriptFullPath & '"'
Exit Run($Cmd)
EndIf
EndFunc ;==>_CreateClock
; Helper Function to Draw a Hand
Func _DrawHand($hGraphic, $hPen, $iX1, $iY1, $iLength, $fAngleDegrees)
Local $fAngleRadians = _Radian($fAngleDegrees)
Local $iX2 = $iX1 + ($iLength * Cos($fAngleRadians))
Local $iY2 = $iY1 + ($iLength * Sin($fAngleRadians))
_GDIPlus_GraphicsDrawLine($hGraphic, $iX1, $iY1, $iX2, $iY2, $hPen)
EndFunc ;==>_DrawHand
; Redraw Clock Function (CallBack by timer)
Func _RedrawClock($hWnd, $iMsg, $iIDTimer, $iTime)
#forceref $hWnd, $iMsg, $iIDTimer, $iTime
Local $iCurrentHour = @HOUR
Local $iCurrentMinute = @MIN
Local $iCurrentSecond = @SEC
Local $iCenterX = $iClockWidth / 2
Local $iCenterY = $iClockHeight / 2
Local $iClockRadius = $iClockWidth / 2
_GDIPlus_GraphicsClear($hGraphicBuffer, 0x00000000)
_GDIPlus_GraphicsDrawImageRect($hGraphicBuffer, $hClockImage, 0, 0, $iClockWidth, $iClockHeight)
; Calculate angles for smooth hand movement
Local $iDisplayHour = $iCurrentHour
If $iDisplayHour > 12 Then $iDisplayHour -= 12
Local $fAngleHours = ($iDisplayHour * 30) + ($iCurrentMinute * 0.5) - 90
_DrawHand($hGraphicBuffer, $hPenHours, $iCenterX, $iCenterY, $iClockRadius * 0.5, $fAngleHours)
Local $fAngleMinutes = ($iCurrentMinute * 6) + ($iCurrentSecond * 0.1) - 90
_DrawHand($hGraphicBuffer, $hPenMinutes, $iCenterX, $iCenterY, $iClockRadius * 0.7, $fAngleMinutes)
Local $fAngleSeconds = ($iCurrentSecond * 6) - 90 ; + ($iCurrentMillisecond * 0.006) ; - 90
_DrawHand($hGraphicBuffer, $hPenSeconds, $iCenterX, $iCenterY, $iClockRadius * 0.8, $fAngleSeconds)
; Draw center bullet
Local $iBulletRadius = 10
_GDIPlus_GraphicsFillEllipse($hGraphicBuffer, $iCenterX - $iBulletRadius, $iCenterY - $iBulletRadius, $iBulletRadius * 2, $iBulletRadius * 2, $hBrushCenter)
; Create HBITMAP and display
Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImageBuffer)
If IsPtr($hHBitmap) Then _WinAPI_BitmapDisplayTransparentInGUI($hHBitmap, $hWnd)
EndFunc ;==>_RedrawClock
; Custom _WinAPI_BitmapDisplayTransparentInGUI Function (by UEZ)
Func _WinAPI_BitmapDisplayTransparentInGUI(ByRef $hHBitmap, ByRef $hGUI, $bReleaseGDI = True)
If Not BitAND(GUIGetStyle($hGUI)[1], $WS_EX_LAYERED) Then Return SetError(1, 0, 0)
Local $tSize = DllStructCreate($tagSIZE), $tSource = DllStructCreate($tagPOINT), $tBlend = DllStructCreate($tagBLENDFUNCTION)
Local Const $hScrDC = _WinAPI_GetDC(0)
Local Const $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC)
Local Const $hOldBitmap = _WinAPI_SelectObject($hMemDC, $hHBitmap)
Local $tBitmapInfo = DllStructCreate($tagBITMAP)
_WinAPI_GetObject($hHBitmap, DllStructGetSize($tBitmapInfo), DllStructGetPtr($tBitmapInfo))
$tSize.X = $tBitmapInfo.bmWidth
$tSize.Y = $tBitmapInfo.bmHeight
$tBlend.Alpha = 0xFF
$tBlend.Format = $AC_SRC_ALPHA
_WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, DllStructGetPtr($tSize), $hMemDC, DllStructGetPtr($tSource), 0, DllStructGetPtr($tBlend), $ULW_ALPHA)
_WinAPI_SelectObject($hMemDC, $hOldBitmap)
_WinAPI_DeleteDC($hMemDC)
_WinAPI_ReleaseDC(0, $hScrDC)
If $bReleaseGDI Then _WinAPI_DeleteObject($hHBitmap)
Return True
EndFunc ;==>_WinAPI_BitmapDisplayTransparentInGUI
; This function draws a clock dial and saves it as a PNG.
Func _CreateAndSaveClockImage($iWidth, $sFilePath)
Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth, $iWidth)
Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hGraphics, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
_GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINT_CLEARTYPEGRIDFIT)
Local $iCenterX = $iWidth / 2
Local $iCenterY = $iWidth / 2
Local $iRadius = $iWidth / 2
; Clear with transparent background (ARGB: A=00)
_GDIPlus_GraphicsClear($hGraphics, 0x00000000)
; Colors from inifile RGB to ARGB
Local $sColorOutline = "0xFF" & StringTrimLeft($mClock.ColorOutline, 2)
Local $sColorTextHour = "0xFF" & StringTrimLeft($mClock.ColorTextHour, 2)
Local $sColorTextMin = "0xFF" & StringTrimLeft($mClock.ColorTextMin, 2)
; Colors and Pens/Brushes
Local $hPenOutline = _GDIPlus_PenCreate($sColorOutline, 5) ; 0xFFEEEEEE
Local $hPenHourMark = _GDIPlus_PenCreate($sColorOutline, 5)
Local $hPenMinuteMark = _GDIPlus_PenCreate($sColorOutline, 2)
Local $hBrushTextMin = _GDIPlus_BrushCreateSolid($sColorTextMin)
Local $hBrushTextHour = _GDIPlus_BrushCreateSolid($sColorTextHour)
; String Format for drawing and measuring text (centered)
Local $hStringFormatCenter = _GDIPlus_StringFormatCreate()
; Check if string format object was successfully created
If Not IsPtr($hStringFormatCenter) Or $hStringFormatCenter = 0 Then
ConsoleWrite("ERROR: Failed to create GDI+ StringFormat object." & @CRLF)
; Clean up other resources before returning failure
_GDIPlus_PenDispose($hPenOutline)
_GDIPlus_PenDispose($hPenHourMark)
_GDIPlus_PenDispose($hPenMinuteMark)
_GDIPlus_BrushDispose($hBrushTextMin)
_GDIPlus_BrushDispose($hBrushTextHour)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ImageDispose($hBitmap)
Return False
EndIf
_GDIPlus_StringFormatSetAlign($hStringFormatCenter, $GDIP_STRINGFORMAT_ALIGNMENT_CENTER)
_GDIPlus_StringFormatSetLineAlign($hStringFormatCenter, $GDIP_STRINGFORMAT_LINEALIGNMENT_CENTER)
; Draw outer circle
Local $iOutlinePadding = 5
_GDIPlus_GraphicsDrawEllipse($hGraphics, $iOutlinePadding, $iOutlinePadding, $iWidth - (2 * $iOutlinePadding), $iWidth - (2 * $iOutlinePadding), $hPenOutline)
; Draw hour and minute marks
For $i = 0 To 59
Local $fAngleDegrees = ($i * 6) - 90
Local $fAngleRadians = _Radian($fAngleDegrees)
Local $iStartX, $iStartY, $iEndX, $iEndY
Local $iMarkLength
If Mod($i, 5) = 0 Then ; Hour marks (every 5 minutes)
$iMarkLength = $iRadius * 0.06
$iStartX = $iCenterX + (($iRadius - ($iRadius * 0.02)) * Cos($fAngleRadians))
$iStartY = $iCenterY + (($iRadius - ($iRadius * 0.02)) * Sin($fAngleRadians))
$iEndX = $iCenterX + (($iRadius - $iMarkLength - ($iRadius * 0.02)) * Cos($fAngleRadians))
$iEndY = $iCenterY + (($iRadius - $iMarkLength - ($iRadius * 0.02)) * Sin($fAngleRadians))
_GDIPlus_GraphicsDrawLine($hGraphics, $iStartX, $iStartY, $iEndX, $iEndY, $hPenHourMark)
Else ; Minute marks
$iMarkLength = $iRadius * 0.04
$iStartX = $iCenterX + (($iRadius - ($iRadius * 0.02)) * Cos($fAngleRadians))
$iStartY = $iCenterY + (($iRadius - ($iRadius * 0.02)) * Sin($fAngleRadians))
$iEndX = $iCenterX + (($iRadius - $iMarkLength - ($iRadius * 0.02)) * Cos($fAngleRadians))
$iEndY = $iCenterY + (($iRadius - $iMarkLength - ($iRadius * 0.02)) * Sin($fAngleRadians))
_GDIPlus_GraphicsDrawLine($hGraphics, $iStartX, $iStartY, $iEndX, $iEndY, $hPenMinuteMark)
EndIf
Next
; Draw numbers (Hours and Minutes)
Local $iHourTextRadius = $iRadius * 0.66 ; Radius for hour numbers (adjust this to move them closer/further from center)
Local $iMinuteTextRadius = $iRadius * 0.86 ; Radius for minute numbers
; Define font families
Local $sFontName = "Times New Roman"
Local $hFontFamily = _GDIPlus_FontFamilyCreate($sFontName)
; Critical check for font family handle
If Not IsPtr($hFontFamily) Or $hFontFamily = 0 Then
ConsoleWrite("ERROR: _GDIPlus_FontFamilyCreate returned an invalid handle for '" & $sFontName & "'. @error is: " & @error & @CRLF)
; Clean up current resources before returning failure
_GDIPlus_PenDispose($hPenOutline)
_GDIPlus_PenDispose($hPenHourMark)
_GDIPlus_PenDispose($hPenMinuteMark)
_GDIPlus_BrushDispose($hBrushTextMin)
_GDIPlus_BrushDispose($hBrushTextHour)
_GDIPlus_StringFormatDispose($hStringFormatCenter)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ImageDispose($hBitmap)
Return False
EndIf
For $i = 1 To 12
; Hour Numbers (1-12)
Local $sHourDigit = $i
Local $fHourAngleDegrees = ($i * 30) - 90
Local $fHourAngleRadians = _Radian($fHourAngleDegrees)
Local $iHourFontSize = 50
Local $hHourFont = _GDIPlus_FontCreate($hFontFamily, $iHourFontSize, 1) ; 1 = Bold typeface
; Check for font handle
If Not IsPtr($hHourFont) Or $hHourFont = 0 Then
ConsoleWrite("ERROR: _GDIPlus_FontCreate failed for hour font. Skipping text drawing." & @CRLF)
ContinueLoop ; Skip drawing this text if font creation failed
EndIf
; Calculate the approximate position for the text bounding box (large enough to contain text)
Local $fApproxTextSize = $iHourFontSize * 1.5
Local $tHourLayoutRect = _GDIPlus_RectFCreate($iCenterX - $fApproxTextSize, $iCenterY - $fApproxTextSize, $fApproxTextSize * 2, $fApproxTextSize * 2)
; Measure text to get its exact dimensions
Local $aHourMeasure = _GDIPlus_GraphicsMeasureString($hGraphics, $sHourDigit, $hHourFont, $tHourLayoutRect, $hStringFormatCenter)
Local $fHourTextWidth = 0, $fHourTextHeight = 0
If Not @error And IsArray($aHourMeasure) And DllStructGetData($aHourMeasure[0], "Width") > 0 And DllStructGetData($aHourMeasure[0], "Height") > 0 Then
$fHourTextWidth = DllStructGetData($aHourMeasure[0], "Width")
$fHourTextHeight = DllStructGetData($aHourMeasure[0], "Height")
Else
; Fallback: Simple estimation if measurement fails
$fHourTextWidth = $iHourFontSize * 0.6 * StringLen($sHourDigit)
$fHourTextHeight = $iHourFontSize * 1.0
ConsoleWrite("WARNING: Failed to measure hour text '" & $sHourDigit & "'. Fallback: Using estimation." & @CRLF)
EndIf
; Calculate the FINAL position for the text, taking into account text dimensions and desired radius
Local $iHourTextX = $iCenterX + ($iHourTextRadius * Cos($fHourAngleRadians)) - ($fHourTextWidth / 2)
Local $iHourTextY = $iCenterY + ($iHourTextRadius * Sin($fHourAngleRadians)) - ($fHourTextHeight / 2)
; Create a layout rectangle specific for drawing the text at the calculated position
Local $tDrawHourLayout = _GDIPlus_RectFCreate($iHourTextX, $iHourTextY, $fHourTextWidth, $fHourTextHeight)
; Draw the string using _GDIPlus_GraphicsDrawStringEx
_GDIPlus_GraphicsDrawStringEx($hGraphics, $sHourDigit, $hHourFont, $tDrawHourLayout, $hStringFormatCenter, $hBrushTextHour)
_GDIPlus_FontDispose($hHourFont)
; Minute Numbers (5, 10, ..., 60)
Local $sMinuteDigit = $i * 5
If $sMinuteDigit = 60 Then $sMinuteDigit = "00"
Local $fMinuteAngleDegrees = ($i * 30) - 90
Local $fMinuteAngleRadians = _Radian($fMinuteAngleDegrees)
Local $iMinuteFontSize = 20
Local $hMinuteFont = _GDIPlus_FontCreate($hFontFamily, $iMinuteFontSize, 1) ; 1 = Bold typeface
; Check for font handle
If Not IsPtr($hMinuteFont) Or $hMinuteFont = 0 Then
ConsoleWrite("ERROR: _GDIPlus_FontCreate failed for minute font. Skipping text drawing." & @CRLF)
ContinueLoop ; Skip drawing this text if font creation failed
EndIf
Local $fApproxMinuteTextSize = $iMinuteFontSize * 1.5
Local $tMinuteLayoutRect = _GDIPlus_RectFCreate($iCenterX - $fApproxMinuteTextSize, $iCenterY - $fApproxMinuteTextSize, $fApproxMinuteTextSize * 2, $fApproxMinuteTextSize * 2)
; Measure text
Local $aMinuteMeasure = _GDIPlus_GraphicsMeasureString($hGraphics, $sMinuteDigit, $hMinuteFont, $tMinuteLayoutRect, $hStringFormatCenter)
Local $fMinuteTextWidth = 0, $fMinuteTextHeight = 0
If Not @error And IsArray($aMinuteMeasure) And DllStructGetData($aMinuteMeasure[0], "Width") > 0 And DllStructGetData($aMinuteMeasure[0], "Height") > 0 Then
$fMinuteTextWidth = DllStructGetData($aMinuteMeasure[0], "Width")
$fMinuteTextHeight = DllStructGetData($aMinuteMeasure[0], "Height")
Else
; Fallback: Simple estimation if measurement fails
$fMinuteTextWidth = $iMinuteFontSize * 0.6 * StringLen($sMinuteDigit)
$fMinuteTextHeight = $iMinuteFontSize * 1.0
ConsoleWrite("WARNING: Failed to measure minute text '" & $sMinuteDigit & "'. Fallback: Using estimation." & @CRLF)
EndIf
Local $iMinuteTextX = $iCenterX + ($iMinuteTextRadius * Cos($fMinuteAngleRadians)) - ($fMinuteTextWidth / 2)
Local $iMinuteTextY = $iCenterY + ($iMinuteTextRadius * Sin($fMinuteAngleRadians)) - ($fMinuteTextHeight / 2)
Local $tDrawMinuteLayout = _GDIPlus_RectFCreate($iMinuteTextX, $iMinuteTextY, $fMinuteTextWidth, $fMinuteTextHeight)
; Draw the string using _GDIPlus_GraphicsDrawStringEx
_GDIPlus_GraphicsDrawStringEx($hGraphics, $sMinuteDigit, $hMinuteFont, $tDrawMinuteLayout, $hStringFormatCenter, $hBrushTextMin)
_GDIPlus_FontDispose($hMinuteFont)
Next
_GDIPlus_FontFamilyDispose($hFontFamily) ; Dispose font family after the loop
; Save the bitmap to a PNG file
Local $bSuccess = _GDIPlus_ImageSaveToFile($hBitmap, $sFilePath)
ConsoleWrite("DEBUG: _GDIPlus_ImageSaveToFile $bSuccess=" & $bSuccess & ", @error=" & @error & @CRLF)
; Add check for file exist and size after saving
If FileExists($sFilePath) And FileGetSize($sFilePath) > 0 Then
Sleep(200) ; Give some time for file system to release the file
Else
ConsoleWrite("ERROR: File save verification failed for '" & $sFilePath & "'. Success: " & $bSuccess & ", Exists: " & FileExists($sFilePath) & ", Size: " & FileGetSize($sFilePath) & @CRLF)
$bSuccess = False
EndIf
; Clean up resources
_GDIPlus_PenDispose($hPenOutline)
_GDIPlus_PenDispose($hPenHourMark)
_GDIPlus_PenDispose($hPenMinuteMark)
_GDIPlus_BrushDispose($hBrushTextHour)
_GDIPlus_BrushDispose($hBrushTextMin)
_GDIPlus_StringFormatDispose($hStringFormatCenter)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ImageDispose($hBitmap)
Return $bSuccess
EndFunc ;==>_CreateAndSaveClockImage
; Make, and read ini to map
Func _GetClockSetting($sIniPath)
If Not FileExists($sIniPath) Then ; make one
Local $sTxt = "" ; Write Example data to the ini file
$sTxt &= "[ClockSetting]" & @CRLF
$sTxt &= "IniFile=" & $sIniPath & @CRLF
$sTxt &= "Image=Default" & @CRLF
$sTxt &= "Width=600" & @CRLF
$sTxt &= "X=-1" & @CRLF
$sTxt &= "Y=-1" & @CRLF
$sTxt &= "ColorSeconds=0xFF0000" & @CRLF
$sTxt &= "ColorMinutes=0x40C880" & @CRLF
$sTxt &= "ColorHours=0x0080C0" & @CRLF
$sTxt &= "ColorCenter=0x000000" & @CRLF
$sTxt &= "ColorTextHour=0xFFFFFF" & @CRLF
$sTxt &= "ColorTextMin=0xFFFFFF" & @CRLF
$sTxt &= "ColorOutline=0xFFFFFF" & @CRLF
$sTxt &= "Alarm=1" & @CRLF
$sTxt &= "AlarmSound=C:\Windows\Media\ringout.wav" & @CRLF
$sTxt &= "AlarmDays=2,3,4,5,6" & @CRLF
$sTxt &= "AlarmTime=17:30" & @CRLF
$sTxt &= "ActivityTimeout=3" & @CRLF
FileWrite($sIniPath, $sTxt)
EndIf
; Read the INI section labelled 'ClockSetting'. This will return a 2 dimensional array.
Local $aArray = IniReadSection($sIniPath, "ClockSetting")
Local $mMap[]
If Not @error Then
For $i = 1 To $aArray[0][0]
$mMap[$aArray[$i][0]] = $aArray[$i][1]
Next
EndIf
; Default colors
If $mMap.ColorSeconds = "" Then $mMap.ColorSeconds = "0xFF0000"
If $mMap.ColorMinutes = "" Then $mMap.ColorMinutes = "0x40C880"
If $mMap.ColorHours = "" Then $mMap.ColorHours = "0x0080C0"
If $mMap.ColorCenter = "" Then $mMap.ColorCenter = "0x000000"
If $mMap.ColorTextHour = "" Then $mMap.ColorTextHour = "0xFFFFFF"
If $mMap.ColorTextMin = "" Then $mMap.ColorTextMin = "0xFFFFFF"
If $mMap.ColorOutline = "" Then $mMap.ColorOutline = "0xFFFFFF"
Return $mMap
EndFunc ;==>_GetClockSetting
; Check Alarm time
Func _CheckAlarm()
If $mClock.Alarm <> "1" Then Return
Local $iPos = StringInStr($mClock.AlarmDays, @WDAY)
If Not @error And $iPos > 0 Then
If $mClock.AlarmTime = @HOUR & ":" & @MIN Then ShellExecute($mClock.AlarmSound)
EndIf
EndFunc ;==>_CheckAlarm
; Set Alarm GUI
Func _SetAlarm()
Local Const $MARGIN = 10
Local $hGUIAlarm = GUICreate("Set Alarm", 300, 260, -1, -1, -1, BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW))
GUICtrlCreateLabel("Select Days:", $MARGIN, $MARGIN, 100, 20)
GUICtrlSetFont(-1, 9, 800)
Local $a_idDays[7]
Local $aDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
Local $iY = $MARGIN + 25
For $i = 0 To UBound($aDays) - 1
$a_idDays[$i] = GUICtrlCreateCheckbox($aDays[$i], 10, $iY, 90, 20)
Local $iPos = StringInStr($mClock.AlarmDays, $i + 1)
If Not @error And $iPos > 0 Then GUICtrlSetState(-1, $GUI_CHECKED)
$iY += (20 + 2)
Next
GUICtrlCreateLabel("Set Time (HH:MM):", 170, $MARGIN, 150, 20)
GUICtrlSetFont(-1, 9, 800) ; Bold
Local $idInputTime = GUICtrlCreateInput($mClock.AlarmTime, 180, 35, 80, 20)
GUICtrlSetFont(-1, 10)
Local $idInfo = GUICtrlCreateLabel("", 100, 65, 190, 100)
GUICtrlSetFont(-1, 10)
$iY += $MARGIN
GUICtrlCreateLabel("Select Sound File:", $MARGIN, $iY, 150, 20)
GUICtrlSetFont(-1, 9, 800) ; Bold
Local $idInputSoundFile = GUICtrlCreateInput($mClock.AlarmSound, $MARGIN, $iY + 25, 240, 20)
Local $idBtnBrowse = GUICtrlCreateButton("...", 260, $iY + 25, 30, 20)
Local $idBtnSetAlarm = GUICtrlCreateButton("Set Alarm", 190, 170, 100, 20 + 5)
GUICtrlSetFont(-1, 10, 800)
GUISetState(@SW_SHOW)
While 1
Local $iMsg = GUIGetMsg()
Switch $iMsg
Case $GUI_EVENT_CLOSE
ExitLoop
Case $idBtnBrowse
Local $sSoundFile = FileOpenDialog("Select Alarm Sound", @WorkingDir, "Sound Files (*.mp3;*.wav)|All Files (*.*)")
If Not @error Then GUICtrlSetData($idInputSoundFile, $sSoundFile)
Case $idBtnSetAlarm
Local $sTime, $sSoundPath, $sDays = "", $sInfo = ""
GUICtrlSetData($idInfo, "")
For $i = 0 To UBound($a_idDays) - 1
If GUICtrlRead($a_idDays[$i]) = $GUI_CHECKED Then $sDays &= $i + 1 & ","
Next
$sDays = StringTrimRight($sDays, 1) ; remove last ","
If $sDays = "" Then $sInfo &= "⚠ Please select at least one day." & @CRLF
$sTime = GUICtrlRead($idInputTime)
If Not StringRegExp($sTime, "^\d{2}:\d{2}$") Then $sInfo &= "⚠ Please enter time in HH:MM format (e.g., 07:30)." & @CRLF
$sSoundPath = "" & GUICtrlRead($idInputSoundFile)
If $sSoundPath = "" Then $sInfo &= "⚠ Please select an sound file."
GUICtrlSetData($idInfo, $sInfo)
If $sInfo <> "" Then ContinueCase ; checks if everything is valid
$mClock.AlarmDays = $sDays
$mClock.AlarmTime = $sTime
$mClock.AlarmSound = $sSoundPath
IniWrite($mClock.IniFile, "ClockSetting", "AlarmDays", $sDays)
IniWrite($mClock.IniFile, "ClockSetting", "AlarmTime", $sTime)
IniWrite($mClock.IniFile, "ClockSetting", "AlarmSound", $sSoundPath)
ExitLoop
EndSwitch
WEnd
GUIDelete($hGUIAlarm)
EndFunc ;==>_SetAlarm
; Set Colors GUI
Func _SetColors()
Local $hGUIColors = GUICreate("Set Colors", 180, 250, -1, -1, -1, $WS_EX_TOOLWINDOW)
GUISetFont(10)
GUICtrlCreateLabel("Seconds hand", 10, 10, 101, 17, 0x0002)
GUICtrlCreateLabel("Minutes hand", 10, 40, 101, 17, 0x0002)
GUICtrlCreateLabel("Hours hand", 10, 70, 101, 17, 0x0002)
GUICtrlCreateLabel("Center Pin", 10, 100, 101, 17, 0x0002)
GUICtrlCreateLabel("Hours Didits", 10, 130, 101, 17, 0x0002)
GUICtrlCreateLabel("Minutes Didits", 10, 160, 101, 17, 0x0002)
GUICtrlCreateLabel("Image Outline", 10, 190, 101, 17, 0x0002)
Local $aNames[8] = [7, "ColorSeconds", "ColorMinutes", "ColorHours", "ColorCenter", "ColorTextHour", "ColorTextMin", "ColorOutline"]
Local $iY = 5
Local $aColors[8][3]
$aColors[0][0] = 7
For $i = 1 To $aColors[0][0]
$aColors[$i][0] = GUICtrlCreateButton("", 120, $iY, 50, 25, 0x8000)
$aColors[$i][1] = $mClock[$aNames[$i]]
GUICtrlSetBkColor(-1, $aColors[$i][1])
If $i < 5 Then GUICtrlSetTip(-1, "This will be in effect after restart the clock")
If $i > 4 Then GUICtrlSetTip(-1, "This will be in effect after deleting the existing clock image")
$iY += 30
Next
Local $idSetColors = GUICtrlCreateButton("Set Colors", 70, $iY, 100, 25)
GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif")
GUISetState(@SW_SHOW)
Local $nMsg, $iChooseColor
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
ExitLoop
Case $aColors[1][0] To $aColors[7][0]
;ConsoleWrite("$nMsg=" & $nMsg & @CRLF)
Local $id = $nMsg - 10
$iChooseColor = _ChooseColor(2, $aColors[$id][1], 2, $hGUIColors)
If $iChooseColor <> -1 Then
$aColors[$id][1] = $iChooseColor
GUICtrlSetBkColor($aColors[$id][0], $aColors[$id][1])
EndIf
Case $idSetColors
For $i = 1 To $aColors[0][0]
$mClock[$aNames[$i]] = $aColors[$i][1]
IniWrite($mClock.IniFile, "ClockSetting", $aNames[$i], $aColors[$i][1])
Next
ExitLoop
EndSwitch
WEnd
GUIDelete($hGUIColors)
EndFunc ;==>_SetColors
Func _ActivityTimeout($iTimeout = 3)
Local Static $iMinute, $iMouseX
Local $aMpos = MouseGetPos()
If $iMouseX <> $aMpos[0] Then
$iMouseX = $aMpos[0]
$iMinute = 0
Return
EndIf
$iMinute +=1
If $iMinute = $iTimeout Then
$iMinute = 0
WinActivate($hGUIClock)
ConsoleWrite("INFO: Activity Timeout triggered." & @CRLF)
EndIf
EndFunc
; https://www.autoitscript.com/forum/topic/213036-%F0%9F%95%91-analog-clock/
;----------------------------------------------------------------------------------------
; Title...........: Analog_Clock.au3
; Description.....: A simple AutoIt script creating a digital analog clock GUI with alarm functionality.
; AutoIt Version..: 3.3.16.1 Author: ioa747 Script Version: 0.1
; Note............: Testet in Win10 22H2
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Math.au3>
#include <Array.au3>
#include <StaticConstants.au3>
#include <TrayConstants.au3>
#include <Misc.au3>
Opt("TrayMenuMode", 3) ; 0=append, 1=no default menu, 2=no automatic check, 4=menuitemID not return
Global $hGuiParent, $hGUIBack, $idBackTheme ; Parent GUI & background GUI
Global $hGUI, $hGraphic ; main clock GUI
Global $hPenSeconds, $hPenMinutes, $hPenHours, $hBrushCenter
Global $mAlarm = _GetClockSetting(StringTrimRight(@ScriptFullPath, 4) & ".ini")
_GDIPlus_Startup()
_CreateClock($mAlarm.width, $mAlarm.x, $mAlarm.y)
;---------------------------------------------------------------------------------------
Func _DrawClock($iWidth, $iX = -1, $iY = -1)
Local $hDLL = DllOpen("user32.dll") ; for _IsPressed
; Tray Menou
Local $idMove = TrayCreateItem("Move")
Local $idSetAlarm = TrayCreateItem("Alarm Setting")
Local $idAlarmActive = TrayCreateItem("Alarm Enable/Disable")
TrayItemSetState($idAlarmActive, ($mAlarm.active = "1" ? $TRAY_CHECKED : $TRAY_UNCHECKED))
Local $idClockSetting = TrayCreateItem("Clock Setting")
TrayCreateItem("") ; separator -----------------------
Local $idClose = TrayCreateItem("Close")
TraySetClick($TRAY_CLICK_SECONDARYUP)
TraySetIcon("mmcndmgr.dll", -15)
TraySetToolTip("Analog Clock")
TraySetState($TRAY_ICONSTATE_SHOW) ; Show the tray menu.
; Clock GUI
$hGUI = GUICreate("Analog Clock", $iWidth, $iWidth, $iX, $iY, $WS_POPUP, $WS_EX_LAYERED, $hGuiParent)
GUISetBkColor(0x00FFFF) ; 0x00FFFF
_WinAPI_SetLayeredWindowAttributes($hGUI, 0x00FFFF) ; 0x00FFFF
GUISetState(@SW_SHOW)
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hPenSeconds = _GDIPlus_PenCreate(0xFFFF0000, 2) ; 0xFFFF0000
$hPenMinutes = _GDIPlus_PenCreate(0xFF0000FF, 8) ; 0xFF0000FF
$hPenHours = _GDIPlus_PenCreate(0xFF008000, 12) ; 0xFF00FF00
$hBrushCenter = _GDIPlus_BrushCreateSolid(0xFF000000) ; 0xFF000000
Local $Tick = -1, $Tack = -1
While True
If $Tick <> @SEC Then
$Tick = @SEC
_RedrawClock($iWidth)
EndIf
If $Tack <> @MIN Then
$Tack = @MIN
_CheckAlarm()
EndIf
Switch TrayGetMsg()
Case $idClose
ExitLoop
Case $idMove
WinActivate($hGuiParent)
While 1
Local $aMpos = MouseGetPos()
WinMove($hGuiParent, '', $aMpos[0], $aMpos[1])
ToolTip("click to drop it", $aMpos[0] + 30, $aMpos[1] - 10)
If _IsPressed("01", $hDLL) Then ExitLoop ; 01 Left mouse button
Sleep(10)
WEnd
ToolTip("")
$mAlarm.x = $aMpos[0]
$mAlarm.y = $aMpos[1]
IniWrite($mAlarm.file, "ClockSetting", "x", $aMpos[0])
IniWrite($mAlarm.file, "ClockSetting", "y", $aMpos[1])
Case $idAlarmActive
If BitAND(TrayItemGetState($idAlarmActive), $TRAY_CHECKED) Then ; If $TRAY_CHECKED
TrayItemSetState($idAlarmActive, $TRAY_UNCHECKED)
IniWrite($mAlarm.file, "ClockSetting", "active", "0")
$mAlarm.active = "0"
Else ; If $TRAY_UNCHECKED
TrayItemSetState($idAlarmActive, $TRAY_CHECKED)
IniWrite($mAlarm.file, "ClockSetting", "active", "1")
$mAlarm.active = "1"
EndIf
Case $idSetAlarm
_SetAlarm()
Case $idClockSetting
ShellExecute($mAlarm.file)
Case $TRAY_EVENT_PRIMARYDOUBLE
WinActivate($hGuiParent)
EndSwitch
WEnd
DllClose($hDLL)
_GDIPlus_PenDispose($hPenSeconds)
_GDIPlus_PenDispose($hPenMinutes)
_GDIPlus_PenDispose($hPenHours)
_GDIPlus_BrushDispose($hBrushCenter)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()
EndFunc ;==>_DrawClock
;---------------------------------------------------------------------------------------
Func _RedrawClock($iWidth)
Local $iHeight = $iWidth
Local $iCenterX = $iWidth / 2
Local $iCenterY = $iHeight / 2
Local $iClockRadius = $iWidth * 0.45
Local $hTransparentBrush = _GDIPlus_BrushCreateSolid(0xFF00FFFF) ;0xFF00FFFF
_GDIPlus_GraphicsFillRect($hGraphic, 0, 0, $iWidth, $iHeight, $hTransparentBrush)
_GDIPlus_BrushDispose($hTransparentBrush)
Local $iCurrentHour = @HOUR
Local $iCurrentMinute = @MIN
Local $iCurrentSecond = @SEC
Local $iDisplayHour = $iCurrentHour
If $iDisplayHour > 12 Then $iDisplayHour -= 12
Local $fAngleHours = ($iDisplayHour * 30) - 90
_DrawHand($hGraphic, $hPenHours, $iCenterX, $iCenterY, $iClockRadius * 0.5, $fAngleHours)
Local $fAngleMinutes = ($iCurrentMinute * 6) - 90
_DrawHand($hGraphic, $hPenMinutes, $iCenterX, $iCenterY, $iClockRadius * 0.7, $fAngleMinutes)
Local $fAngleSeconds = ($iCurrentSecond * 6) - 90
_DrawHand($hGraphic, $hPenSeconds, $iCenterX, $iCenterY, $iClockRadius * 0.8, $fAngleSeconds)
Local $iBulletRadius = 10
_GDIPlus_GraphicsFillEllipse($hGraphic, $iCenterX - $iBulletRadius, $iCenterY - $iBulletRadius, $iBulletRadius * 2, $iBulletRadius * 2, $hBrushCenter)
EndFunc ;==>_RedrawClock
;---------------------------------------------------------------------------------------
Func _DrawHand($hGraphic, $hPen, $iX1, $iY1, $iLength, $fAngleDegrees)
Local $fAngleRadians = _Radian($fAngleDegrees)
Local $iX2 = $iX1 + ($iLength * Cos($fAngleRadians))
Local $iY2 = $iY1 + ($iLength * Sin($fAngleRadians))
_GDIPlus_GraphicsDrawLine($hGraphic, $iX1, $iY1, $iX2, $iY2, $hPen)
EndFunc ;==>_DrawHand
;---------------------------------------------------------------------------------------
Func _CreateClock($iWidth, $iX = -1, $iY = -1)
$hGuiParent = GUICreate("GuiParent", 10, 10, $iX, $iY, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TRANSPARENT))
$hGUIBack = GUICreate("GUIBack", $iWidth, $iWidth, 10 - ($iWidth / 2), 10 - ($iWidth / 2), $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_MDICHILD), $hGuiParent)
$idBackTheme = GUICtrlCreatePic(@ScriptDir & "\Clock-600.gif", 0, 0, $iWidth, $iWidth)
GUISetState(@SW_SHOW, $hGUIBack)
GUISetState(@SW_SHOW, $hGuiParent)
Local $aPos = WinGetPos($hGuiParent)
_DrawClock($iWidth, $aPos[0] - ($iWidth / 2) + 5, $aPos[1] - ($iWidth / 2) + 5)
EndFunc ;==>_CreateClock
;---------------------------------------------------------------------------------------
Func _GetClockSetting($sIniPath)
If Not FileExists($sIniPath) Then ; make one
Local $sTxt = "" ; Write Example data to the ini file
$sTxt &= "[ClockSetting]" & @CRLF
$sTxt &= "file=" & $sIniPath & @CRLF
$sTxt &= "width=600" & @CRLF
$sTxt &= "x=-1" & @CRLF
$sTxt &= "y=-1" & @CRLF
$sTxt &= "sound=C:\Windows\Media\ringout.wav" & @CRLF
$sTxt &= "day=1,2,3,4,5" & @CRLF
$sTxt &= "active=1" & @CRLF
$sTxt &= "time=17:30" & @CRLF
FileWrite($sIniPath, $sTxt)
EndIf
; Read the INI section labelled 'ClockSetting'. This will return a 2 dimensional array.
Local $aArray = IniReadSection($sIniPath, "ClockSetting")
Local $mMap[]
If Not @error Then
For $i = 1 To $aArray[0][0]
$mMap[$aArray[$i][0]] = $aArray[$i][1]
Next
EndIf
Return $mMap
EndFunc ;==>_GetClockSetting
;---------------------------------------------------------------------------------------
Func _CheckAlarm()
If $mAlarm.active <> "1" Then Return
Local $iPos = StringInStr($mAlarm.day, @WDAY)
If Not @error And $iPos > 0 Then
If $mAlarm.time = @HOUR & ":" & @MIN Then ShellExecute($mAlarm.sound)
EndIf
EndFunc ;==>_CheckAlarm
;---------------------------------------------------------------------------------------
Func _SetAlarm()
Local Const $MARGIN = 10
Local $hGUI = GUICreate("Set Alarm", 300, 260, -1, -1, -1, BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW))
GUICtrlCreateLabel("Select Days:", $MARGIN, $MARGIN, 100, 20)
GUICtrlSetFont(-1, 9, 800)
Local $a_idDays[7]
Local $aDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
Local $iY = $MARGIN + 25
For $i = 0 To UBound($aDays) - 1
$a_idDays[$i] = GUICtrlCreateCheckbox($aDays[$i], 10, $iY, 90, 20)
Local $iPos = StringInStr($mAlarm.day, $i + 1)
If Not @error And $iPos > 0 Then GUICtrlSetState(-1, $GUI_CHECKED)
$iY += (20 + 2)
Next
GUICtrlCreateLabel("Set Time (HH:MM):", 170, $MARGIN, 150, 20)
GUICtrlSetFont(-1, 9, 800) ; Bold
Local $idInputTime = GUICtrlCreateInput($mAlarm.time, 180, 35, 80, 20)
GUICtrlSetFont(-1, 10)
Local $idInfo = GUICtrlCreateLabel("", 100, 65, 190, 100)
GUICtrlSetFont(-1, 10)
$iY += $MARGIN
GUICtrlCreateLabel("Select Sound File:", $MARGIN, $iY, 150, 20)
GUICtrlSetFont(-1, 9, 800) ; Bold
Local $idInputSoundFile = GUICtrlCreateInput($mAlarm.sound, $MARGIN, $iY + 25, 240, 20)
Local $idBtnBrowse = GUICtrlCreateButton("...", 260, $iY + 25, 30, 20)
Local $idBtnSetAlarm = GUICtrlCreateButton("Set Alarm", 190, 170, 100, 20 + 5)
GUICtrlSetFont(-1, 10, 800)
GUISetState(@SW_SHOW)
While 1
Local $iMsg = GUIGetMsg()
Switch $iMsg
Case $GUI_EVENT_CLOSE
ExitLoop
Case $idBtnBrowse
Local $sSoundFile = FileOpenDialog("Select Alarm Sound", @WorkingDir, "Sound Files (*.mp3;*.wav)|All Files (*.*)")
If Not @error Then GUICtrlSetData($idInputSoundFile, $sSoundFile)
Case $idBtnSetAlarm
Local $sTime , $sSoundPath, $sDays = "", $sInfo = ""
GUICtrlSetData($idInfo, "")
For $i = 0 To UBound($a_idDays) - 1
If GUICtrlRead($a_idDays[$i]) = $GUI_CHECKED Then $sDays &= $i + 1 & ","
Next
$sDays = StringTrimRight($sDays, 1) ; remove last ","
If $sDays = "" Then $sInfo &= "⚠ Please select at least one day." & @CRLF
$sTime = GUICtrlRead($idInputTime)
If Not StringRegExp($sTime, "^\d{2}:\d{2}$") Then $sInfo &= "⚠ Please enter time in HH:MM format (e.g., 07:30)." & @CRLF
$sSoundPath = GUICtrlRead($idInputSoundFile)
If $sSoundPath = "" Then $sInfo &= "⚠ Please select an sound file."
GUICtrlSetData($idInfo, $sInfo)
If $sInfo <> "" Then ContinueCase ; checks if everything is valid
$mAlarm.day = $sDays
$mAlarm.time = $sTime
$mAlarm.sound = $sSoundPath
IniWrite($mAlarm.file, "ClockSetting", "day", $sDays)
IniWrite($mAlarm.file, "ClockSetting", "time", $sTime)
IniWrite($mAlarm.file, "ClockSetting", "sound", $sSoundPath)
ExitLoop
EndSwitch
WEnd
GUIDelete($hGUI)
EndFunc ;==>_SetAlarm
; https://www.autoitscript.com/forum/topic/213036-%F0%9F%95%91-analog-clock/
;----------------------------------------------------------------------------------------
; Title...........: AnalogClockGdi.au3
; Description.....: A simple AutoIt script creating a digital analog clock GUI.
; AutoIt Version..: 3.3.16.1 Author: ioa747 Script Version: 0.1
; Note............: Testet in Win10 22H2
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Math.au3>
#include <Array.au3>
#include <StaticConstants.au3>
Global $hGUI, $hGraphic ; main GUI
Global $hGUIBack, $hGraphicBack ; background GUI
Global $hPenSeconds, $hPenMinutes, $hPenHours, $hBrushCenter
_GDIPlus_Startup()
_CreateClock(600)
Func _DrawClock($iWidth, $iX = -1, $iY = -1)
Local $iHeight = $iWidth
$hGUI = GUICreate("Analog Clock", $iWidth, $iHeight, $iX, $iY, $WS_POPUP, $WS_EX_LAYERED, $hGUIBack)
GUISetBkColor(0x00FFFF) ; 0x00FFFF
_WinAPI_SetLayeredWindowAttributes($hGUI, 0x00FFFF) ; 0x00FFFF
GUISetState(@SW_SHOW)
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hPenSeconds = _GDIPlus_PenCreate(0xFFFF0000, 2)
$hPenMinutes = _GDIPlus_PenCreate(0xFF0000FF, 8)
$hPenHours = _GDIPlus_PenCreate(0xFF00FF00, 12)
$hBrushCenter = _GDIPlus_BrushCreateSolid(0xFF000000)
Local $sTime, $Tick = -1
While True
If $Tick <> @SEC Then
$sTime = @HOUR & ":" & @MIN & ":" & @SEC
ConsoleWrite("- " & $sTime & @CRLF)
$Tick = @SEC
_RedrawClock($iWidth)
EndIf
Switch GUIGetMsg()
Case -3 ; $GUI_EVENT_CLOSE
ExitLoop
EndSwitch
WEnd
_GDIPlus_GraphicsDispose($hGraphicBack)
_GDIPlus_PenDispose($hPenSeconds)
_GDIPlus_PenDispose($hPenMinutes)
_GDIPlus_PenDispose($hPenHours)
_GDIPlus_BrushDispose($hBrushCenter)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()
EndFunc ;==>_DrawClock
Func _RedrawClock($iWidth)
Local $iHeight = $iWidth
Local $iCenterX = $iWidth / 2
Local $iCenterY = $iHeight / 2
Local $iClockRadius = $iWidth * 0.5
Local $hTransparentBrush = _GDIPlus_BrushCreateSolid(0xFF00FFFF)
_GDIPlus_GraphicsFillRect($hGraphic, 0, 0, $iWidth, $iHeight, $hTransparentBrush)
_GDIPlus_BrushDispose($hTransparentBrush)
Local $iCurrentHour = @HOUR
Local $iCurrentMinute = @MIN
Local $iCurrentSecond = @SEC
Local $iDisplayHour = $iCurrentHour
If $iDisplayHour > 12 Then $iDisplayHour -= 12
Local $fAngleHours = ($iDisplayHour * 30) - 90
_DrawHand($hGraphic, $hPenHours, $iCenterX, $iCenterY, $iClockRadius * 0.5, $fAngleHours)
Local $fAngleMinutes = ($iCurrentMinute * 6) - 90
_DrawHand($hGraphic, $hPenMinutes, $iCenterX, $iCenterY, $iClockRadius * 0.7, $fAngleMinutes)
Local $fAngleSeconds = ($iCurrentSecond * 6) - 90
_DrawHand($hGraphic, $hPenSeconds, $iCenterX, $iCenterY, $iClockRadius * 0.8, $fAngleSeconds)
Local $iBulletRadius = 10
_GDIPlus_GraphicsFillEllipse($hGraphic, $iCenterX - $iBulletRadius, $iCenterY - $iBulletRadius, $iBulletRadius * 2, $iBulletRadius * 2, $hBrushCenter)
EndFunc ;==>_RedrawClock
Func _DrawHand($hGraphic, $hPen, $iX1, $iY1, $iLength, $fAngleDegrees)
Local $fAngleRadians = _Radian($fAngleDegrees)
Local $iX2 = $iX1 + ($iLength * Cos($fAngleRadians))
Local $iY2 = $iY1 + ($iLength * Sin($fAngleRadians))
_GDIPlus_GraphicsDrawLine($hGraphic, $iX1, $iY1, $iX2, $iY2, $hPen)
EndFunc ;==>_DrawHand
Func _CreateClock($iWidth, $iX = -1, $iY = -1)
Local $iHeight = $iWidth
$hGUIBack = GUICreate("Clock Background", $iWidth, $iHeight, $iX, $iY, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW))
GUISetBkColor(0x00FFFF) ; 0x00FFFF
_WinAPI_SetLayeredWindowAttributes($hGUIBack, 0x00FFFF) ; 0x00FFFF
GUISetState(@SW_SHOW)
; Get the graphic context for the background GUI
$hGraphicBack = _GDIPlus_GraphicsCreateFromHWND($hGUIBack)
_GDIPlus_GraphicsSetSmoothingMode($hGraphicBack, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
Local $iCenterX = $iWidth / 2
Local $iCenterY = $iHeight / 2
Local $iClockRadius = $iWidth * 0.5
Local $iTextRadius = $iClockRadius * 0.90 ; Adjust this value for number placement (closer to edge)
For $i = 1 To 12
Local $sDigit = $i
Local $fAngleDegrees = ($i * 30) - 90
Local $fAngleRadians = _Radian($fAngleDegrees)
Local $iTextX = $iCenterX + ($iTextRadius * Cos($fAngleRadians))
Local $iTextY = $iCenterY + ($iTextRadius * Sin($fAngleRadians))
Local $iDigitWidth = 36 ; Estimate based on font size 30
Local $iDigitHeight = 30 ; Estimate based on font size 30
; Draw the number - 0xFFFFFFFF = White color for numbers (ARGB)
_GDIPlus_GraphicsDrawString($hGraphicBack, $sDigit, $iTextX - ($iDigitWidth / 2), $iTextY - ($iDigitHeight / 2), "Arial", 30, Default, 0xFFFFFFFF)
Next
_DrawClock($iWidth, $iX, $iY)
EndFunc ;==>_DrawStaticClockBackground
첨부 파일 :
출처 : 바로가기
'Autoit3 및 PureBASIC' 카테고리의 다른 글
| PureBasic 6.21 한글 언어팩 (4) | 2026.01.14 |
|---|---|
| Mount ISO _ 오토잇 소스 (3) | 2025.07.25 |
| PureBasic 6.20 한글 언어팩(PureBasic 6.20 Korean Language) (4) | 2025.06.06 |
| *.Wim 파일 1회 부팅 (3) | 2023.07.01 |
| AutoIt3 3.3.16.1 (19th September, 2022) (0) | 2023.03.26 |
Comments
