1 (изменено: Zanoza, 2011-08-11 00:06:33)

Тема: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Доброе время суток. У меня вопрос как создать  с помощью AHK простой будильник.
Дабы он просто при указанном мной времени  заиграл  мной указанный звук?
Прошу не проходите мимо , дайте совет! Желательно с GUI чтоб  можно время менять .
PS/я пытался но всё плохо
Зарание  благодарен !
Извиняюсь ( Win7 / 32 bit )
Любые варианты прошу....

Win10 x64

2

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Советую не мучиться с событиями таймера.
Самое простое решение - шедулер (планировщик заданий).

Частенько использую такой вот "будильник" при работе за ПК:

1) пуск - выполнить:
2) AT 2:25 msg * ALERT

На такой основе и делай - конфигуратор (который и есть будильник, есди его запустить с параметрами) задаёт время, сообщение, и имя файла; добавляй задание типа:
> alarm.exe /t=6:00 /msg="blabla" /snd=1.wav

Далее разбор строки запуска.

С рюшечками-гуи'шками думаю уж сам разберёшься.

3

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Тут готовое решение.

4 (изменено: hojo, 2012-06-22 12:31:41)

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

вот я нарисовал сегодня утром простой будильник )) не везде конечно рационально, но вроде работает.


; === GUI ===

Gui, Add, Tab,, Settings
Gui, Add, Text, vText01 x25  y92  w150 h15, Hour:
Gui, Add, Text, vText02 x25  y135 w150 h15, Min:

FormatTime, Current_Time, , HH:mm:ss tt
Gui, Add, Text, vTime x210 y200, %Current_Time%
Gui, Show, h175 w404 Center, Alarm Clock

Gui, Add, Text, vText04 x25  y175 w150 h15, Sec:
Gui, Add, Text, vText05 x25  y72  w150 h15, 
Gui, Add, Text, vText06 x125  y72  w150 h15, 

; === Buttons ===

Gui, Add, Button, x25  y35 w65 h29 , F1.Start
Gui, Add, Button, x185 y35 w75 h29 , F3.Reload

; === Edits ===

Gui, Add, Edit, vEdit1  x25  y111 w165 h49 r1
Gui, Add, Edit, vEdit2  x25  y151 w165 h49 r1
Gui, Add, Edit, vEdit4  x25  y191 w165 h49 r1

GuiControl,, Edit1, 0
GuiControl,, Edit2, 0
GuiControl,, Edit3, 0

; === Checks ===

Gui, Add, Checkbox, vCheck1 x200  y111, Msg need?

; === Main ===

Gui, Show, h234 w285, WakeUpper :D

SetTimer, Loop, 1000

Loop:
FormatTime, Current_Time, , HH:mm:ss tt
GuiControl, , Time, %Current_Time%

Return

GuiClose:
ExitApp
Return

;---------------------- Start -----------------------

ButtonF1.Start:

Gui, Submit, NoHide

met1:

ah:=A_Hour+edit1
am:=A_Min+edit2
as:=A_Sec+edit4

met2:

if am>60
{
am:=am-60
ah:=ah+1
goto met2
}

met3:

if as>60
{
as:=as-60
am:=am+1
goto met3
}

ah1:=ah-A_Hour
am1:=am-A_Min
as1:=as-A_Sec

GuiControl,, Text05,  Start in %A_Hour% %A_Min% %A_Sec%
GuiControl,, Text06,  Stop in %ah% %am% %as%

h:=Edit1*3600000
m:=Edit2*60000
s:=Edit4*1000

sleep %h%
sleep %m%
sleep %s%

SoundBeep, 2000, 250
SoundBeep, 2000, 650


if Check1=1
{
msgbox, Wake up! %ah1% hr, %am1% min, %as1% sek.
}

Return

;--------- Reload

ButtonF3.Reload:

Gui, Submit, NoHide

reload

Return

;------------------------------


F1::
goto,ButtonF1.Start
Return

F3::
goto,ButtonF3.Reload
Return

5

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Меня интересует не столько сам будильник, сколько метод привязки действий ко времени, собственно, можно сказать шедулер. Виндовый встроенный и специализированные утилиты по разным причинам не устраивают.
В варианте hoyo, насколько я понимаю, при более или менее длительном периоде ожидания возможны существенные погрешности из-за использования sleep.
В готовом решении текущее время ежесекундно сравнивается с заданным, что не кажется мне рациональным.
Навскидку приходит мысль о промежуточном варианте - sleep процентов на 90 от заданного промежутка, потом сверка через меньшие промежутки. К примеру, нужное время наступит через 10 часов 15 минут - sleep на 9 часов, сверка, а далее - в зависимости от результатов сверки, если к примеру, расхождение невелико (секунды) - сверки через полчаса, затем через 10 минут, затем только ежесекундно.
Но чтобы решить, стоит ли вообще этим заниматься, мне не хватает информации, если можно, подскажите пожалуйста:
1. Хотя бы приблизительно, какова максимально возможная погрешность при использовании sleep, при условии, что пиковые нагрузки на проц могут достигать 100% и довольно часто?
2. Чревато ли чем-либо существенным применение ежесекундной сверки для других процессов? Возможно на современном железе это и неощутимо, но вот хоть убейте, не приемлет этого мое эстетическое чувство
3. Нет ли иных средств добиться того же? В частности, какой метод использует встроенный шедулер и нельзя ли использовать его помимо этого шедулера, или шедулер и есть сам метод?

____________________________________
будьте снисходительны - я профан

BIG BROTHER IS WATCHING YOU.

6

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Korobkof пишет:

1. Хотя бы приблизительно, какова максимально возможная погрешность при использовании sleep, при условии, что пиковые нагрузки на проц могут достигать 100% и довольно часто?

Sleep гарантирует лишь, что поток будет бездействовать как минимум указанное число миллисекунд. После того, как указанное время процесс пробудет в состоянии ожидания(waiting), если его приоритет выше чем у всех остальных потоков, ожидающих выполнение- он сразу начинает выполняться. Иначе он переходит в состояние готовности(Ready) и как только не будет готовых потоков с более высоким приоритетом он начнёт выполняться. Однако если он в течение примерно четырёх секунд так и не получит процессорного времени, то его приоритет будет динамически повышен до 15(приоритет реального времени) на 1 квант, затем приоритет будет сброшен обратно. Так что раз в 5 секунд ваш поток должен получать процессорное время.

Korobkof пишет:

2. Чревато ли чем-либо существенным применение ежесекундной сверки для других процессов? Возможно на современном железе это и неощутимо, но вот хоть убейте, не приемлет этого мое эстетическое чувство

Нет, ничем не чревато, просто глупо.

Korobkof пишет:

3. Нет ли иных средств добиться того же? В частности, какой метод использует встроенный шедулер и нельзя ли использовать его помимо этого шедулера, или шедулер и есть сам метод?

Таймер, он вроде для таких ситуаций и существует .

7

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

А чем в данном случае таймер отличается от Sleep?

A timer might not be able to run as often as specified under the following conditions:

1. Other applications are putting a heavy load on the CPU.

По-моему, как раз постоянная сверка с системным временем может обеспечить точность.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8 (изменено: Александр_, 2012-06-25 02:59:49)

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

teadrinker пишет:

А чем в данном случае таймер отличается от Sleep?

Sleep переводит поток в состояние ожидания(или тревожного ожидания, если SleepEx), а таймер инициирует событие(отправка сообщения/запуск функции обратного вызова). Короче это два разных системных сервиса- NtDelayExecution и NtUserSetTimer. Нам, очевидно, не нужно блокировать текущий поток- поэтому выбираем таймер.

9

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Если оба этих сервиса не могут гарантировать точность, зачем вообще их выбирать для данной задачи?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

10

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

teadrinker пишет:

Если оба этих сервиса не могут гарантировать точность, зачем вообще их выбирать для данной задачи?

Могут, для планировщика в самый раз. Тут ведь счёт не на миллисекунды идёт. Для критичных по времени ситуаций есть мультимедийный таймер, но и он ничего не гарантирует, в силу архитектуры планировщика потоков. Так что оптимальный вариант- это обычный таймер.
Кстати, в AHK функция Sleep не вызывает соответствующую WinAPI-функцию, а уходит в цикл, где проверяет очередь сообщений и ещё что-то там, так что здешний Sleep совсем не годится.

11

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Ясно, спасибо. Уже разобрался, удалил своё сообщение, но ты опередил меня с ответом.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

12

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

teadrinker пишет:

Ясно, спасибо. Уже разобрался, удалил своё сообщение, но ты опередил меня с ответом.

Тогда и я свой снёс, а то он странно смотрится . Но только я забыл указать одну важную деталь(слона не приметил:))- использовать нужно таймер с автоматическим сбросом(CreateWaitableTimer, SetWaitableTimer).

13

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

В качестве будильника сработает и обычный, если задать время одним промежутком.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

teadrinker пишет:

В качестве будильника сработает и обычный, если задать время одним промежутком.

А если время переведут?

15

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

А что, должно повлиять? Тогда учесть, задавая промежуток.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

teadrinker пишет:

А что, должно повлиять?

Ну а как иначе. Допустим сейчас час ночи, тогда задачи "выполнить через час" и "выполнить в два часа ночи" разнятся, поскольку переведя часы на час назад можно отложить выполнение условия. Кстати, WaitableTimer работает со временем по Гринвичу, так что смена локального времени на неё не повлияет.

17

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Премного благодарен за разъяснения. В какой-то момент, а точнее в момент

Александр_ пишет:

Таймер, он вроде для таких ситуаций и существует .

померещилась мне окончательная ясность и я сваял такой, с позволения сказать, код:

Gui, Add, DateTime, vTimeToAlert 1 w60, HH:mm
Gui, Add, Button, r1 w60, CTAPT
Gui, Show, AutoSize
Return
  
ButtonCTAPT:

Gui, Submit
StringMid, TimeH, TimeToAlert, 9, 2
StringMid, TimeM, TimeToAlert, 11, 2
TimeToWait:=(TimeH*60*60*1000+TimeM*60*1000)-(A_Hour*60*60*1000+A_Min*60*1000)
if (TimeToWait<=0 )
TimeToWait:= TimeToWait+24*60*60*1000

SetTimer, Alert, %TimeToWait%
return

Alert:
msgbox its work!!!
SetTimer, Alert, Off 
ExitApp

Но теперь я так понимаю, что речь-то шла не про тот timer...

Александр_ пишет:

... NtUserSetTimer ... CreateWaitableTimer ... SetWaitableTimer ...

Пойду попытаюсь вкурить что-нибудь на этот счет...

____________________________________
будьте снисходительны - я профан

BIG BROTHER IS WATCHING YOU.

18

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Кто-то на этом форуме уже жаловался на заболевание "гуманитарий головного мозга", вот у меня тоже... в тяжелой форме... Посему укурка доступных источников что-то застопорилась. Все попавшиеся мне описания WaitableTimer подразумевают наличие массы базовых познаний, которыми я не располагаю. Ну или массы времени, чтобы получить эти познания, которое тоже в нехватке . Применительно к AHK нашлось такое решение. Можно, конечно, попытаться тупо скопировать нужный кусок, но мое эстетическое чувство, этот генератор проблем и убийца времени, при одной такой мысли начинает буянить. А раз так, в расчете на еще одну любезность корифеев, вываливаю свои вопросы.

Handle:=DLLCall("CreateWaitableTimer" 
            ,"char *", 0 
            ,"Int",0 
            ,"Str",name, "UInt")

Насколько я понимаю, создается тот самый таймер, ему передаются параметры - дважды 0 (что это?) и "name" (как поясняет автор скрипта это - произвольное имя таймера; оно зачем - можно потом по нему обращаться к нему? или как?); "UInt", видимо, - тип возвращаемого значения (зачем оно и каким может быть?).

DLLCall("CancelWaitableTimer","UInt",handle)

Судя по слову "Cancel" и параметру, соответствующему ранее возвращенному значению, в зависимости от последнего таймер отменяется (отключается? уничтожается?). Это что-то типа ErrorLevel?

DLLCall("SetWaitableTimer" 
          ,"Uint", handle 
          ,"Int64*", duetime 
          ,"Int", 1000 
          ,"uint",0 
          ,"uint",0 
          ,"int",resume)

Тут вообще понятно только относительно "duetime", это время срабатывания таймера в формате UTC-file-time. Что задают остальные передаваемые параметры? И что дает эта конструкция, выходных-то данных никаких нет? Или выполнение скрипта на этом месте останавливается до наступления указанного времени?

Signal:=DLLCall("WaitForSingleObject" 
            ,"Uint", handle 
            ,"Uint",-1) 
DllCall("CloseHandle", uint, Handle)

Имеет ли этот участок кода отношение к таймеру и если да, то какое?

____________________________________
будьте снисходительны - я профан

BIG BROTHER IS WATCHING YOU.

19 (изменено: Александр_, 2012-06-27 16:53:08)

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Korobkof пишет:

Насколько я понимаю, создается тот самый таймер

Да.

Korobkof пишет:

ему передаются параметры - дважды 0 (что это?)

Первый- это указатель на атрибуты защиты, указывая ноль мы говорим, что особых атрибутов нам не надо, пусть будут по-умолчанию. Почти всегда передают ноль, более подробно стоит разбирать этот параметр только тем, кто всерьёз собирается программировать под windows.
Второй отвечает за сброс события: 0- автоматический сброс, 1- ручной. Если таймер используется только один раз, то не важно что передавать.

Korobkof пишет:

"name" (как поясняет автор скрипта это - произвольное имя таймера; оно зачем - можно потом по нему обращаться к нему? или как?);

Не совсем произвольное- это имя объекта ядра. Нас оно не интересует, можно передавать ноль- тогда будет создан неименованный объект.

Korobkof пишет:

"UInt", видимо, - тип возвращаемого значения (зачем оно и каким может быть?).

Да, это тип возвращаемого значения. Возвращается описатель(handle) созданного таймера, он нам необходим для дальнейшей работы с таймером. Тип должен быть "ptr", дальше будет пример, где все типы указаны правильно.

Korobkof пишет:

Судя по слову "Cancel" и параметру, соответствующему ранее возвращенному значению, в зависимости от последнего таймер отменяется (отключается? уничтожается?). Это что-то типа ErrorLevel?

Скорее "отключается", т.е. объект "таймер" всё ещё существует и его можно использовать. Для уничтожения таймера нужно закрыть все хендлы функцией CloseHandle.

Korobkof пишет:

Тут вообще понятно только относительно "duetime", это время срабатывания таймера в формате UTC-file-time. Что задают остальные передаваемые параметры?

1- ранее созданный таймер
2- либо дата первого срабатывания, либо промежуток через который таймер должен сработать, чтобы задать промежуток нужно передать отрицательное значение(например -50000000, означает через 5 секунд).
3- период срабатывания в миллисекундах. Т.е. после того как таймер сработает первый раз, он будет ещё и периодически срабатывать через указанный тут период. 0- значит не нужно периодического срабатывания.
4- функция завершения ожидания, в данном случае она нас не интересует из-за особенностей её срабатывания(поток должен быть в состоянии ожидания для её срабатывания)
5- параметр, который будет передан в функцию из четвёртого параметра
6- не помню, всегда ноль ставят .

Korobkof пишет:

И что дает эта конструкция, выходных-то данных никаких нет? Или выполнение скрипта на этом месте останавливается до наступления указанного времени?

Функция возвращает 0 в случае неудачи, иначе таймер успешно установлен. Т.е. объект "таймер" перейдёт в сигнальное состояние в указанное время.

Korobkof пишет:

Имеет ли этот участок кода отношение к таймеру и если да, то какое?

WaitForSingleObject- ожидает перехода таймера(на самом деле почти любого объекта) в сигнальное состояние.
CloseHandle- уничтожает таймер.
WaitForSingleObject блокирует поток до наступления события, а AHK не поддерживает многопоточность. Для выхода из этой ситуации можно воспользоваться функциями из этой темы(из второго поста).
Пример:

#persistent
DetectHiddenWindows On
WinGet, hWnd, id, % "ahk_classAutoHotkey ahk_pid" . DllCall("GetCurrentProcessId")
OnMessage(0x401, "DlgProc")
hTimer := DllCall("CreateWaitableTimer", "ptr", 0, "int", 1, "ptr", 0, "ptr")
if (hTimer == 0)
{
   msgbox не удалось создать таймер
   ExitApp
}
EventProc := CreateWaitFunc(hTimer, hWnd, 0x401)
liDueTime := -50000000
x := DllCall("SetWaitableTimer", "ptr", hTimer, "int64*", liDueTime, "int", 0, "ptr", 0, "ptr", 0, "int", 0)
if (!x)
{
   msgbox не удалось установить таймер
   ExitApp
}
DllCall("CloseHandle", "ptr", DllCall("CreateThread", "ptr", 0, "ptr", 0, "ptr", 0|EventProc, "ptr", 0, "uint", 0, "ptr", 0))
return

DlgProc(wParam, lParam, msg, hWnd)
{
   global EventProc
   if(msg==0x401)
   {
      msgbox таймер сработал
	  FreeWaitFunc(EventProc)
	  DllCall("CloseHandle", "ptr", wParam)
	  ExitApp
   }
}

20

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Александр_ пишет:

ahk_classAutoHotkey

Здесь, очевидно, пробел выпал.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

21

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

teadrinker пишет:
Александр_ пишет:

ahk_classAutoHotkey

Здесь, очевидно, пробел выпал.

Нет, я специально не оставлял пробелов ни в классе, ни в PID'е.

22

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Хм, а зачем? Greystile? Так ведь код читать неудобно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

23

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

teadrinker пишет:

Хм, а зачем? Greystyle? Так ведь код читать неудобно.

Дело вкуса, я наоборот не люблю когда один аргумент(или как эту конструкцию назвать?) разбивается на два слова.

24

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Параметр.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

25

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Упс Спасибо, очень доходчиво про timer. Но пример, чувствую, долго жевать буду. В функцию глянул, даже пытаться разбирать не стану , это уже явно выше моего потолка.
А пока традиционно дилетантский вопрос: не решается ли проблема однопоточности путем запуска нескольких экземпляров AHK? Ну, к примеру, - в одном экземпляре - таймер, а во втором - шедулер с конструкцией, отслеживающей его состояние?

BIG BROTHER IS WATCHING YOU.

26

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Korobkof пишет:

не решается ли проблема однопоточности путем запуска нескольких экземпляров AHK? Ну, к примеру, - в одном экземпляре - таймер, а во втором - шедулер с конструкцией, отслеживающей его состояние?

Решится, но лучше использовать те функции. Причины:
1) непредвиденное падение экземпляра с таймером приведёт к зависанию ожидающего скрипта.
2) новый скрипт будет съедать значительно больше ресурсов, чем поток.
3) в начале ожидания курсор примет "ожидающий вид"(как при запуске оконных приложений) и провесит так несколько секунд.
Так что лучше скопировать функции FreeWaitFunc и CreateWaitFunc в отдельный файл и при необходимости подключать его к скрипту(#Include FileName).

27

Re: AHK: Можно-ли сделать с помощью AHK БУДИЛЬНИК ?

Александр_ пишет:
teadrinker пишет:

Хм, а зачем? Greystyle? Так ведь код читать неудобно.

Дело вкуса...

Именно так.