v1.3+(아이콘 적용버전) _첨부파일에만 있음


v1.3


v1.2

v1.0



@수정사항
=================v1.3+ [25.05.02]
 #_UI버튼 아이콘 적용 (첨부파일에 따로 있음)
 #_v1.3 버전도 함께 포합되어 있으니 가볍게 쓰실분은 v1.3 사용 권장

=================v1.3 [25.05.01]
 #_설정창 기능 추가
 #_채팅 단축키 기능 추가
 #_기타 알람시간등 오류 수정

=================v1.2 [25.04.28]
 #_알람시간,남은시간 텍스트 컬러 변경
 #_gui창 사이즈 축소(화면을 너무 많이 차지함)

=================v1.1 [25.04.28]
 #_항상 화면위에 뜨고 알림음을 좀 길게함
 #_새로 타이머를 실행시 전에 적용한 리스트가 제대로 안뜨는 문제를 수정했습니다.
 #_컨트롤+F를 누르면 남은시간등을 챗창에 입력하는 기능이 있엇는데, 컨트롤+G키로 바꾸었습니다. 현재시간 남
   은시간등이 표기됩니다.
 #_버튼과 남은시간의 좌우 위치를 바꿈(스킬사용시 x버튼 클릭 빈도 최소화)


@기타사항
#_일정 시간을 기준으로 타이머를 실행하는 프로그램입니다.
#_알람이 울릴때 화면 중앙 상단에 툴팁이 나타났다가 사라지고 동시에 알림음이 들립니다. 그리고 알람은 자동으로 재개 됩니다.
#_사용자가 단축키를 지정하고 채팅을 미리 입력하여 필요시에 단축키를 눌렀을때 채팅을 바로 입력해 주는 기능이 있습니다.

#_시간되면 비프음 들리고 마우스근처에 툴팁생겻다가 5초뒤 사라져요 그리고 타이머 계속 진행됩니다. 사진처럼 1분이면 1분마다 비프음 들려요

 #_챗창 입력 내용을 바꾸려면
    ClipText =
(
##렙업구간 : act1(1-11) // act2(12-18) // act3(19-23) // act4(24-31) // act5(32-36) // 카우방(28-33)  ##웨이 필요한곳 말해주세요  ##담방시간 %NextTime%  ##현재시간 %NowTime%  ##남은시간 %RemainingTime%
)

구간중 괄호 안쪽의 ##렙업구간 이부분부터 괄호 안까지 수정하시면 됩니다.



#_오토핫키v1 버전으로 컴파일 해서 쓰시면 됩니다.(오토핫키 사용법은 인터넷 참조)
#_번거로우신분은 첨부파일로 쓰시면됩니다




챗GPT 98%
제노력 2%로 만들었습니다.
(AI 무섭네요 프로그래머 전부 직장잃게 생김...)

제가 한눈팔면 시계를 안봐서 알람 만들어봤어요




;=======================================여기부터 복사

; Timer_Hotkey_Combo.ahk
#Persistent
#SingleInstance Force
CoordMode, Gui, screen
SetTitleMatchMode, 2
SetBatchLines, -1
OnMessage(0x201, "WM_LBUTTONDOWN") ; 마우스 왼쪽버튼 눌림 감지
; 전역 변수
global BaseHour := ""
global BaseMinute := ""
global IntervalMin := 15
global RemainingSeconds := 0
global TimerRunning := false
global isExpanded := false

IniFilePath := A_ScriptDir . "config.ini"
;IniFilePath := A_ScriptDir . "HotkeySettings.ini"

; 핫키용 배열
hotkeys := []
texts := []

; INI에서 시간 관련 설정 불러오기
IniRead, BaseHour, %IniFilePath%, Time, Hour, 12
IniRead, BaseMinute, %IniFilePath%, Time, Minute, 0
IniRead, IntervalMin, %IniFilePath%, Time, Interval, 15

; GUI 구성
Gui, +AlwaysOnTop +ToolWindow -Caption
Gui, Color, 004488
Gui, Font, s12 Bold, Segoe UI

Gui, Add, Button, gExitApp1 vExitBtn x10 y5 w30 h30 c00ffff BackgroundColor, X
Gui, Add, Button, gToggleSettingsSection x+10 y5 w80 h30 c3f7ab5, 설정 열기



Gui, Add, Button, gApplyAll vApplyBtn x+25 y5 w40 h30 cFFFFFF BackgroundTrans, 적용
Gui, Add, Button, gStartTimer vStartBtn x+15 y5 w40 h30 Disabled cFFFFFF BackgroundTrans, 시작
Gui, Add, Button, gStopTimer vStopBtn x+15 y5 w40 h30 Disabled cFFFFFF BackgroundTrans, 정지
Gui, Font, s14 Bold, Segoe UI
Gui, Add, Text, vTimeText x+30 y7 w150 h30 cFFFFFF BackgroundTrans, 현 시간:
Gui, Add, Text, vCountdownText x+1 y7 w440 h30 cFF8E7F BackgroundTrans, 남은 시간:
Gui, Font, s12 Bold, Segoe UI

BaseHour1 := BaseHour+1
BaseMinute1 := BaseMinute+1
Gui, Add, Text, vIntervalLabel1 x10 y60 w160 h30 cFFFFFF BackgroundTrans, 알람기준 시간 :    시_
Gui, Add, DropDownList, vHourDDL x+1 y57 w45 h150 Choose%BaseHour1% cFFFFFF BackgroundTrans, % LoopList(0,23)
Gui, Add, Text, vIntervalLabel2 x+20 y60 w30 h30 cFFFFFF BackgroundTrans, 분_
Gui, Add, DropDownList, vMinuteDDL x+1 y57 w45 h150 Choose%BaseMinute1% cFFFFFF BackgroundTrans, % LoopList(0,59)
Gui, Add, Text, vIntervalLabel3 x+20 y60 w70 h30 cFFFFFF BackgroundTrans, 간격(분)_
Gui, Add, DropDownList, vIntervalDDL x+1 y57 w45 h150 Choose%IntervalMin% cFFFFFF BackgroundTrans, % LoopList(1,59)


; 핫키 설정 GUI - 하단에 텍스트 영역 포함
Gui, Add, Button,  x5 y110 w70 h30 c3f7ab5 vHotkeyClear1 gClearHotkey, 핫키삭제
Gui, Add, Text, x90 y110 c0FFFFF vHotkeyLabel, *핫키설정
Gui, Add, Text, x220 y110 c0FFFFF vHotkeyLabel1, *내 용
;Loop, 6 {
;    Gui, Add, Hotkey, vHotkey%A_Index% x+10 w80
;}

; 개별 라벨과 핫키 생성
Gui, Add, Text, vLabel1 x10 y150 w70 h25 cFFFFFF, 텍스트 1
Gui, Add, Hotkey, vHotkey1 x+10 w120 gUpdateHotkeyLabel
Gui, Add, Edit, vText1 x+10  w670 Hidden

Gui, Add, Text, vLabel2 x10 y+30 w70 h25 cFFFFFF, 텍스트 2
Gui, Add, Hotkey, vHotkey2 x+10  w120 gUpdateHotkeyLabel
Gui, Add, Edit, vText2 x+10 w670 Hidden

Gui, Add, Text, vLabel3 x10 y+30 w70 h25 cFFFFFF, 텍스트 3
Gui, Add, Hotkey, vHotkey3 x+10 w120 gUpdateHotkeyLabel
Gui, Add, Edit, vText3 x+10 w670 Hidden

Gui, Add, Text, vLabel4 x10 y+30 w70 h25 cFFFFFF, 텍스트 4
Gui, Add, Hotkey, vHotkey4 x+10 w120 gUpdateHotkeyLabel
Gui, Add, Edit, vText4 x+10 w670 Hidden

Gui, Add, Text, vLabel5 x10 y+30 w70 h25 cFFFFFF, 텍스트 5
Gui, Add, Hotkey, vHotkey5 x+10 w120 gUpdateHotkeyLabel
Gui, Add, Edit, vText5 x+10 w670 Hidden

Gui, Add, Text, vLabel6 x10 y+30 w70 h25 cFFFFFF, 텍스트 6
Gui, Add, Hotkey, vHotkey6 x+10 w120 gUpdateHotkeyLabel
Gui, Add, Edit, vText6 x+10 w670 Hidden


; 핫키 INI 불러오기
Loop, 6 {
    idx := A_Index
    IniRead, hkey, %IniFilePath%, Hotkeys, Hotkey%idx%,
    IniRead, txt, %IniFilePath%, Hotkeys, Text%idx%,
    if (hkey != "" && hkey != "ERROR") {
        GuiControl,, Hotkey%idx%, %hkey%
        Hotkey, %hkey%, DoAction%idx%, On
        hotkeys[idx] := hkey
    }
    if (txt != "ERROR") {
        GuiControl,, Text%idx%, %txt%
        texts[idx] := txt
    }
}
Notetext := "*함수 : 현재시간[%now%]  /알람시간[%AlarmTime%] / 남은시간[%mins% : %secs%] /알람간격[%IntervalMin%분]"
Gui, Add, Edit, vNotetextEdit x10 y+10 w900 h30 c00FFFF ReadOnly -E0x200, %Notetext%



Gui, Show, x10 y10 w928 h40, D2R타이머
; 처음 실행 시 핫키 설정 라벨, 입력창들 숨기기
GuiControl, Hide, HotkeyLabel
Loop, 6 {
    GuiControl, Hide, Hotkey%A_Index%
    GuiControl, Hide, Label%A_Index%
    GuiControl, Hide, Text%A_Index%
}
GuiControl,, Button2, 설정 열기  ; 버튼 텍스트도 초기화

SetTimer, UpdateTime, 1000
return

; 시간 표시 업데이트
;global AlarmTime := ""
;global mins := 0
;global secs := 0

UpdateTime:
global AlarmTime, mins, secs, RemainingSeconds, IntervalMin
FormatTime, now,, HH:mm
GuiControl,, TimeText, 현 시간: %now%

if (TimerRunning && (BaseHour != "") && (BaseMinute != ""))
{
    FormatTime, NowHour,, HH
    FormatTime, NowMinute,, mm
    FormatTime, NowSecond,, ss
    NowTotalSec := (NowHour * 3600) + (NowMinute * 60) + NowSecond
    BaseTotalSec := (BaseHour * 3600) + (BaseMinute * 60)
    ElapsedSec := NowTotalSec - BaseTotalSec
    if (ElapsedSec < 0)
        ElapsedSec += 86400
    IntervalSec := IntervalMin * 60
    NextAlarmInSec := IntervalSec - Mod(ElapsedSec, IntervalSec)
    if (NextAlarmInSec = IntervalSec)
        NextAlarmInSec := 0
    RemainingSeconds := NextAlarmInSec
    mins := Floor(RemainingSeconds / 60)
    secs := Mod(RemainingSeconds, 60)
    AlarmTimeSec := NowTotalSec + RemainingSeconds
    if (AlarmTimeSec >= 86400)
        AlarmTimeSec -= 86400

    AlarmHour := Floor(AlarmTimeSec / 3600)
    AlarmMinute := Floor(Mod(AlarmTimeSec, 3600) / 60)
    AlarmTime := Format("{:02}:{:02}", AlarmHour, AlarmMinute)

    ; 남은 시간과 알람시간 표시
    FormatTimeText := Format("알람시간: {:02}:{:02} (간격: {:02}분)      남은시간: {:02}분{:02}초", AlarmHour, AlarmMinute, IntervalMin, mins, secs)
    GuiControl,, CountdownText, %FormatTimeText%

    if (RemainingSeconds = 0) {
        ShowNiceTooltip(IntervalMin " 분 단위 알람! 현재시간:"now)
        PlayFancyAlarm()

        ; ⏭ 다음 알람 계산 즉시 수행
        BaseTotalSec := AlarmTimeSec
        ElapsedSec := 0
        RemainingSeconds := IntervalSec
        mins := Floor(RemainingSeconds / 60)
        secs := Mod(RemainingSeconds, 60)
        AlarmTimeSec := BaseTotalSec + IntervalSec
        if (AlarmTimeSec >= 86400)
            AlarmTimeSec -= 86400
        AlarmHour := Floor(AlarmTimeSec / 3600)
        AlarmMinute := Floor(Mod(AlarmTimeSec, 3600) / 60)
        AlarmTime := Format("{:02}:{:02}", AlarmHour, AlarmMinute)
        FormatTimeText := Format("알람시간: {:02}:{:02}     남은시간: {:02}:{:02}", AlarmHour, AlarmMinute, mins, secs)
        GuiControl,, CountdownText, %FormatTimeText%
        }
}
/*
else
{
    ; 타이머가 꺼져 있을 경우
    AlarmTime := "알람없음"
    mins := 0
    secs := 0
    RemainingSeconds := 0
    GuiControl,, CountdownText, 알람 없음
}
*/
return



ApplyAll:  ;;===============================================================적용버튼
Gui, Submit, NoHide



; 기준시간 저장
BaseHour := HourDDL
BaseMinute := MinuteDDL
IntervalMin := IntervalDDL

IniWrite, %BaseHour%, %IniFilePath%, Time, Hour
IniWrite, %BaseMinute%, %IniFilePath%, Time, Minute
IniWrite, %IntervalMin%, %IniFilePath%, Time, Interval
GuiControl,, CountdownText, 기준시간: %BaseHour%:%BaseMinute% (간격: %IntervalMin%분)
GuiControl, Enable, StartBtn
SoundBeep, 600, 300

; 핫키 저장
Loop, 6 {
    idx := A_Index
    hotkeyVar := Hotkey%idx%
    textVar := Text%idx%
    if (hotkeyVar != "") {
        Hotkey, %hotkeyVar%, DoAction%idx%, On
        hotkeys[idx] := hotkeyVar
        texts[idx] := textVar
        IniWrite, %hotkeyVar%, %IniFilePath%, Hotkeys, Hotkey%idx%
        IniWrite, %textVar%, %IniFilePath%, Hotkeys, Text%idx%
    }
}
return  ;;===============================================================적용버튼



ToggleSettingsSection:
isExpanded := !isExpanded
Loop, 3 {
    GuiControl, % isExpanded ? "Show" : "Hide", IntervalLabel%A_Index%
}
    GuiControl, % isExpanded ? "Show" : "Hide", HourDDL
    GuiControl, % isExpanded ? "Show" : "Hide", MinuteDDL
    GuiControl, % isExpanded ? "Show" : "Hide", IntervalDDL
    GuiControl, % isExpanded ? "Show" : "Hide", HotkeyLabel
    GuiControl, % isExpanded ? "Show" : "Hide", HotkeyLabel1
    GuiControl, % isExpanded ? "Show" : "Hide", HotkeyClear1
Loop, 6 {
    GuiControl, % isExpanded ? "Show" : "Hide", Label%A_Index%
    GuiControl, % isExpanded ? "Show" : "Hide", Text%A_Index%
    GuiControl, % isExpanded ? "Show" : "Hide", Hotkey%A_Index%  ; 추가된 부분
}
    GuiControl, % isExpanded ? "Show" : "Hide", NotetextEdit
GuiControl,, Button2, % isExpanded ? "설정 닫기" : "설정 열기"
Gui, Show, AutoSize
return

StartTimer:
TimerRunning := true
GuiControl, Disable, ApplyBtn
GuiControl, Disable, StartBtn
GuiControl, Enable, StopBtn
SoundBeep, 750, 300
return

StopTimer:
TimerRunning := false
GuiControl, Enable, ApplyBtn
GuiControl, Enable, StartBtn
GuiControl, Disable, StopBtn
GuiControl,, CountdownText, 기준시간 적용 필요
SoundBeep, 400, 300
return

ExitApp1:
ExitApp
return





LoopList(min, max) {
    list := ""
    Loop % (max - min + 1)
        list .= (A_Index - 1 + min) "|"
    return list
}

ShowNiceTooltip(msg) {
    static TooltipGuiExists := false
    if (TooltipGuiExists)
        Gui, TooltipGuiID: Destroy
    TooltipGuiExists := true
    Gui, TooltipGuiID: New, +AlwaysOnTop -Caption +ToolWindow +E0x20 +E0x80000 +LastFound
    Gui, TooltipGuiID: Color, 59227C
    WinSet, Transparent, 127
    Gui, TooltipGuiID: Font, s12 Bold, Segoe UI
    Gui, TooltipGuiID: Add, Text, cffffff BackgroundTrans Center hwndhText, %msg%
    GuiControlGet, Pos, TooltipGuiID: Pos, %hText%
    textWidth := PosW + 20
    textHeight := PosH + 20
    xPos := (A_ScreenWidth - textWidth) / 2
    yPos := 80
    WinSet, Region, 0-0 W%textWidth% H%textHeight% R10-10, ahk_id %hText%
    Gui, TooltipGuiID: Show, x%xPos% y%yPos% w%textWidth% h%textHeight% NoActivate
    SetTimer, RemoveSplash, -5000
}


RemoveSplash:
Gui, TooltipGuiID: Destroy
return

PlayFancyAlarm() {
    freqs := [800, 1000, 1200, 1400, 1600]
    for index, freq in freqs {
        SoundBeep, %freq%, 100
        Sleep, 50
    }
    Sleep, 200
    freqs := [1600, 1400, 1200, 1000, 800]
    for index, freq in freqs {
        SoundBeep, %freq%, 100
        Sleep, 50
    }
    Sleep, 200
    SoundBeep, 1500, 200
    Sleep, 100
    SoundBeep, 700, 400
}

DoAction1:
    if (texts[1] != "")
        HandleHotkey(texts[1])
return

DoAction2:
    if (texts[2] != "")
        HandleHotkey(texts[2])
return

DoAction3:
    if (texts[3] != "")
        HandleHotkey(texts[3])
return

DoAction4:
    if (texts[4] != "")
        HandleHotkey(texts[4])
return

DoAction5:
    if (texts[5] != "")
        HandleHotkey(texts[5])
return

DoAction6:
    if (texts[6] != "")
        HandleHotkey(texts[6])
return

HandleHotkey(text) {
    FormatTime, now,, HH:mm
    expandedText := text
    expandedText := StrReplace(expandedText, "%now%", now)
    expandedText := StrReplace(expandedText, "%AlarmTime%", AlarmTime)
    expandedText := StrReplace(expandedText, "%mins%", mins)
    expandedText := StrReplace(expandedText, "%secs%", secs)
    expandedText := StrReplace(expandedText, "%RemainingSeconds%", RemainingSeconds)
    expandedText := StrReplace(expandedText, "%IntervalMin%", IntervalMin)
    Clipboard := expandedText
    ;Run, notepad.exe
    ;WinWaitActive, ahk_class Notepad
    Send, {Enter}
    Sleep, 200
    Send, ^v
    Sleep, 200
    Send, {Enter}
}

ClearHotkey:
    loop, 6 {
        idx := A_Index
        ; GUI에서 현재 핫키 가져오기
        GuiControlGet, currentHotkey,, Hotkey%idx%

        ; 기존 핫키 비활성화 (예외 처리)
        if (currentHotkey != "") {
            try {
                Hotkey, %currentHotkey%, Off
            }
        }

        ; GUI 초기화
        GuiControl,, Hotkey%idx%,

        ; INI 초기화
        IniWrite, % "", %IniFilePath%, Hotkeys, Hotkey%idx%

        ; 변수 초기화
        hotkeys[idx] := ""
    }
return



UpdateHotkeyLabel:
    Gui, Submit, NoHide
    Loop, 6 {
        GuiControlGet, currentHotkey,, Hotkey%A_Index%
        if (currentHotkey != "") {
            newText := "텍스트 " A_Index " (" currentHotkey ")"
        } else {
            newText := "텍스트 " A_Index
        }
        GuiControl,, Label%A_Index%, %newText%
    }
return

;gui마우스이동 함수
WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) {
    MouseGetPos,,, ControlUnderMouse
    ; 컨트롤 이름을 얻어서, 버튼들 클릭한 경우에는 이동 금지
    if (ControlUnderMouse ~= "^(Buttond*)?$") ; 버튼 이름(Button1, Button2 등)일 경우
        return
    PostMessage, 0xA1, 2,,, A
}

;=======================================여기까지 복사