Что нового

Сообщение об изменении времени

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Можно ли зарегистрировать функцию, которая срабатывала бы каждую минуту в тот момент, когда меняется время. Т.е что бы срабатывала в тот момент, когда на часах 00 секунд?
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Проверяй в цикле @SEC, и если равно 0, то какое-то действие.
 

AZJIO

Меценат
Меценат
Сообщения
2,903
Репутация
1,200
Попробовал на основе счётчика, который в тоже время синхронизирует внутреннее время с внешним, но при этом вызов однократный, без проверок в цикле. При синхронизации просто вычисляется разница во времени и учитывается при следующем вызове. Точность в пределах одной секунды, потому что 00.000 сек и 00.999 секунд воспринимается как 00.
Код:
$clo = 0
$iSyn = 0

$hGui = GUICreate('My Program', 250, 260)
$iStatusBar = GUICtrlCreateLabel($clo, 19, 10, 150, 55)
GUICtrlSetFont(-1, 18) 
GUISetState()


AdlibRegister('_Call00', (60 - @SEC) * 1000) ; Синхронизвция при старте
_Call00() ; вызов каждую минуту

Do
Until GUIGetMsg() = -3

Func _Call00()
	If Not @SEC Then
		Switch @SEC
			Case 1 To 30
				AdlibRegister('_Call00', (60 - @SEC) * 1000) ; Синхронизвция при расинхронизации
				$iSyn = -1
			Case 31 To 59
				AdlibRegister('_Call00', (120 - @SEC) * 1000) ; Синхронизвция при расинхронизации
				$iSyn = 1
			Case Else
				If $iSyn Then
					AdlibRegister('_Call00', 60 * 1000) ; В обычный режим
					$iSyn = 0
				EndIf
		EndSwitch
	EndIf
	$clo += 1
	GUICtrlSetData($iStatusBar, $clo)
EndFunc


Так как выше указанный пример сложно тестить (рассинхронизацию не дождаться), вот пример синхронизации миллисекунд по такому же алгоритму.
Код:
$clock = 0
$iSyn = 1

$hGui = GUICreate('Раз в  секунду', 210, 95)
GUISetFont(10)
GUISetBkColor(0xc0b075)

GUICtrlCreateLabel(' Секунд = ' & @LF & ' Триггер синхр = ' & @LF & ' AdlibRegister = ' & @LF & ' Offset = ', 10, 10, 130, 70)
GUICtrlSetBkColor(-1, 0xfdffae)
$iStatistics = GUICtrlCreateLabel('', 140, 10, 60, 70)
GUICtrlSetBkColor(-1, 0xf8ed83)
GUISetState()

$pause = 1000 - @MSEC
AdlibRegister('_Call00', $pause) ; Синхронизвция при старте
GUICtrlSetData($iStatistics, $clock & @LF & $iSyn & @LF & $pause)

Do
Until GUIGetMsg() = -3

Func _Call00()
	Switch @MSEC
		; Case 100 To 500 ; Допуск рассинхронизации 100
		Case 20 To 500 ; Допуск рассинхронизации 20
			AdlibRegister('_Call00', 1000 - @MSEC) ; Синхронизвция при расинхронизации
			$iSyn = -1
			$pause = 1000 - @MSEC
			; Case 501 To 800 ; Допуск рассинхронизации 100
		Case 501 To 980 ; Допуск рассинхронизации 20
			AdlibRegister('_Call00', 2000 - @MSEC) ; Синхронизвция при расинхронизации
			$iSyn = 1
			$pause = 2000 - @MSEC
		Case Else
			If $iSyn Then
				AdlibRegister('_Call00', 1000) ; В обычный режим
				$iSyn = 0
			EndIf
			$pause = 1000
	EndSwitch
	$clock += 1
	; If Not $iSyn Then $pause = 1000 ; это только для статистики "AdlibRegister = "
	GUICtrlSetData($iStatistics, $clock & @LF & $iSyn & @LF & $pause & @LF & @MSEC)
EndFunc   ;==>_Call00


С точностью до миллисекунд (обновлено 6 раза).
Код:
#include <StaticConstants.au3>
$clock = 0
$iSyn = 1 ; 1 чтобы при первом вызове функции установить 60000, если отклонения нет.

$hGui = GUICreate('Раз в минуту', 210, 105)
GUISetFont(10)
GUISetBkColor(0xc0b075)

GUICtrlCreateLabel(' Таймер секунд = ', 10, 10, 130, 25, $SS_LEFTNOWORDWRAP)
GUICtrlSetBkColor(-1, 0xfdffae)
$iTimer = GUICtrlCreateLabel('', 140, 10, 60, 25)
GUICtrlSetBkColor(-1, 0xf8ed83)

GUICtrlCreateLabel(' Минут = ' & @LF & ' Триггер синхр = ' & @LF & ' AdlibRegister = ', 10, 35, 130, 60)
GUICtrlSetBkColor(-1, 0xfdffae)
$iStatistics = GUICtrlCreateLabel('', 140, 35, 60, 60)
GUICtrlSetBkColor(-1, 0xf8ed83)

GUISetState()

$msec = (60 - Number(@SEC & '.' & @MSEC)) * 1000
; Exit MsgBox(0, 'Сообщение', $msec & @LF & Number(@SEC & '.' & @MSEC))
AdlibRegister('_Call00', $msec) ; Синхронизвция при старте
GUICtrlSetData($iStatistics, $clock & @LF & $iSyn & @LF & $msec)

$s = 0
$sec = 0
$tmp = 0
Do
	$s += 1
	If $s = 20 Then ; Проверка каждые 20 * 10 = 200 миллисекунд
		$s = 0
		$sec = @SEC
		If $tmp <> $sec Then
			GUICtrlSetData($iTimer, $sec) ; здесь таймер чтобы следить за переключением времени
			$tmp = $sec
		EndIf
	EndIf
Until GUIGetMsg() = -3

Func _Call00()
	$msec = Number(@SEC & '.' & @MSEC)
	Switch $msec
		Case 0.1 To 30 ; Допуск рассинхронизации 100
			$msec = (60 - $msec) * 1000
			AdlibRegister('_Call00', $msec) ; Синхронизвция при расинхронизации
			$iSyn = -1
		Case 30 To 59.9 ; Допуск рассинхронизации 100
			$msec = (120 - $msec) * 1000
			AdlibRegister('_Call00', $msec) ; Синхронизвция при расинхронизации
			$iSyn = 1
		Case Else
			If $iSyn Then
				$msec = 60000 ; 60 * 1000
				AdlibRegister('_Call00', $msec) ; В обычный режим
				$iSyn = 0
			EndIf
	EndSwitch
	$clock += 1
	If Not $iSyn Then $msec = 60000 ; это только для статистики "AdlibRegister = "
	GUICtrlSetData($iStatistics, $clock & @LF & $iSyn & @LF & $msec)
EndFunc   ;==>_Call00
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,323
Мой вариант.
Код:
HotKeySet('{Esc}', '_Exit')

If Int(@SEC) And Int(@MSEC) Then
	AdlibRegister('_00_sec', (60 - @SEC) * 1000 - @MSEC)
Else
	Call('_MyFunc_00_sec', @MSEC)
	AdlibRegister('_00_sec', 60000)
EndIf

While 1
	Sleep(500)
WEnd

Func _00_sec()
	If Not Int(@SEC) Then Call('_MyFunc_00_sec', @MSEC)
	AdlibRegister('_00_sec', (60 - @SEC) * 1000 - @MSEC)
EndFunc   ;==>_00_sec

Func _MyFunc_00_sec($s_Msec)
	Local $s_NowTime = StringFormat('%02d:%02d:%02d\t%03d msec\r\n', @HOUR, @MIN, @SEC, $s_Msec)
	DllCall('user32.dll', 'bool', 'MessageBeep', 'uint', 0)
	ConsoleWrite($s_NowTime)
	FileWrite(@ScriptDir & '\timer.txt', $s_NowTime)
EndFunc   ;==>_MyFunc_00_sec

Func _Exit()
	Exit
EndFunc   ;==>_Exit
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
AZJIO
Интересные прмеры!
А как сделать AdlibRegister которая бы сработала ровно в 10 часов 22 минуты.
И как лучше поступить, если мне нужно мониторить 5 разных времен.
Создать 5 функций Adlib?

Я хочу вот что сделать, есть к примеру внутри какой то функции один параметр, который привязан ко времени, я хочу в 10:43 устанавливать этот параметр в 10, а в 15:16 устанавливать в 20.

К примеру, я зарегистрировал универсальную функцию, которая срабатывает в 10:43
и в 15:16
Внутри, я проверяю, если @HOUR&@MIN = 1043 Or @HOUR&@MIN = 1516 то устанавливаю параметр. НО. допустим, в 1040 появляется msgbox, который закрывается в 1050
Adlib сработает сразу после закрытия как и положено, но как теперь определить что мне нужно сделать, ведь @HOUR&@MIN уже не будет равно 1043.

Как лучше это сделать? А то у меня кроме как регистрации 5 различных функций, нет идей.
 

AZJIO

Меценат
Меценат
Сообщения
2,903
Репутация
1,200
Запустить отдельный процесс - отдельный скрипт (/AutoIt3ExecuteScript). Обойти MsgBox не получится. Когда он появляется скрипт не выполняется, а функции Adlib видимо регистрируют аналогично _Timer_SetTimer, то есть на уровне системы в очередь ставит сообщения.
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Спасибо всем! Кажется мне подойдет вот это
 

AZJIO

Меценат
Меценат
Сообщения
2,903
Репутация
1,200
inververs
Посмотри ещё это, я там ставил время срабатывания через реестр. Скрипт один раз запускаешь, в ком-строке указывая дату и время. При этом скрипт запускается каждый раз при запуске Windows и если дата не соответствует, то скрипт завершается, а если дата и время просрочена, то скрипт выполняет задуманное, а если дата сегодняшняя, а время не подошло, то висит в процессах. Конечно этот вариант рассчитан на компьютер, который на ночь выключается, и поэтому не висит в процессах если не назначенный день.


Добавлено:
Сообщение автоматически объединено:

MsgBox лучше выдать отдельным процессом, в том числе /AutoIt3ExecuteLine
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
AZJIO
Посмотрим. Спасибо!
А msgbox - это просто пример блокирующих функций для простоты, у меня же такие есть в winhttp, и если хост в офлайне, то скрипт может на долго "задуматься" и запросто пропустит нужную минуту, когда его "отпустит" ).
 

InnI

AutoIT Гуру
Сообщения
4,982
Репутация
1,460
inververs [?]
ведь @HOUR&@MIN уже не будет равно 1043
А почему вы проверяете на строгое равенство, а не на "больше или равно"? Ведь в случае ">=" условие тоже сработает сразу после закрытия MsgBox :scratch:
 

InnI

AutoIT Гуру
Сообщения
4,982
Репутация
1,460
inververs [?]
как организовать проверку пяти времен?
Я думаю так же, как и одного: сравнить текущее время с заданным значением. И так для всех. А дальше по обстоятельствам. Судя по вашим комментариям, вам главное не пропустить время. Т.е. если оно даже прошло, то всё равно выполнить задачу. Вот я и предложил ">=".
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
InnI
Как сравнивать со знаком ">="
Код:
Local $pause
$now = 2301 ;Текущее время
If $now>='0000' Then
	$pause = 0
EndIf
If $now>='2300' Then
	$pause = 23
EndIf
If $now>='0250' Then
	$pause = 200
EndIf
ConsoleWrite( $pause& @LF)

Должно быть 23, но устанавливает 200
 

AZJIO

Меценат
Меценат
Сообщения
2,903
Репутация
1,200
inververs
Если $pause1, $pause2, $pause3, то проблемы не будет. Метки времени то должны быть не в одной переменной.
">=" лучше чем "=", гарантирует от зависаний и прочих нестыковок, гарантируя обязательное выполнение.
 

MnM

Post-Hardcore
Сообщения
679
Репутация
90
inververs
у вас срабатывают условия 2 и 3 последнее же перекрывает 2, значит все правильно. Надо было в одном блоке if...endif устанавливать :smile:


Добавлено:
Сообщение автоматически объединено:

Ошибочка, там 1 условие тоже срабатывает если все в 1 блок запихнуть, => последнее перекрывает все предыдущие установки
 

InnI

AutoIT Гуру
Сообщения
4,982
Репутация
1,460
inververs [?]
Как сравнивать со знаком ">="
Если сравнивать через полночь, то тут уже дату нужно прикручивать. Иначе сложно понять - время прошло или ещё не наступило.
 
Верх