Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.03.25;
Скачать: CL | DM;

Вниз

будильник на API   Найти похожие ветки 

 
Dmitry_177   (2006-10-20 12:26) [0]

Хочу сделать будильник на API, используя функции CreateWaitableTimer и SystemTimeToFileTime. Т.к. в них нельзя задать определенное время, например в 18:00 чтобы прозвенел, нужно при установке таймера посчитать разницу между 18:00 и системным временем, и поставить этот интервал, чтобы через такой момент времени сработал будильник... Помогите пожалуйста с реализацией


const
 HOUR = 18;

var
 hTimer: THandle;
 sysTime: TSystemTime;
...

hTimer := CreateWaitableTimer(nil, false, nil);
GetLocalTime(sysTime);   // получили системное время
HOUR - sysTime.wHour;   // как получить разницу? Подскажите пожалуйста...

SetWaitableTimer(hTimer, ..., 0, nil, nil, false);


 
Sapersky   (2006-10-20 12:56) [1]

Из справки по SetWaitableTimer, параметр pDueTime:

Positive values indicate absolute time. Negative values indicate relative time.

Т.е. определённое время задать можно.


 
Dmitry_177   (2006-10-20 13:50) [2]

А как его задать? что-то мне не очень понятно...


 
Sapersky   (2006-10-20 14:18) [3]

Сам же написал: SystemTimeToFileTime


 
Leonid Troyanovsky ©   (2006-10-20 14:33) [4]


> Dmitry_177   (20.10.06 13:50) [2]

> А как его задать? что-то мне не очень понятно...


var
 st: TSystemTime;
 ft: TFileTime;
 h: THandle;
 ..
 DateTimeToSystemTime(Now, st);
 st.wHour := ..;
 SystemTimeToFileTime(st, ft);
 LocalFileTimeToFileTime(ft, ft);
 h := CreateWaitableTimer(nil, True, nil);
 win32Check(SetWaitableTimer(h, Int64(ft), 0, ..));


--
Regards, LVT.


 
Dmitry_177   (2006-10-20 16:10) [5]

а вот так нельзя сделать?

var
 hTimer: THandle;
 sysTime: TSystemTime;
begin
hTimer := CreateWaitableTimer(nil, false, nil);
sysTime.wHour := 18;
sysTime.wMinute := 0;
sysTime.wSecond := 0;
SystemTimeToFileTime(sysTime, fTime);
SetWaitableTimer(hTimer, fTime, 0, nil, nil, false);
end;


только если честно не очень понятно как он должен сработать? толи callback функция должна быть, толи поток создать толи еще что?


 
Leonid Troyanovsky ©   (2006-10-21 12:07) [6]


> Dmitry_177   (20.10.06 16:10) [5]

> а вот так нельзя сделать?


> sysTime.wHour := 18;

У SystemTime есть еще и wYear & etc.

> SystemTimeToFileTime(sysTime, fTime);

+
LocalFileTimeToFileTime(fTime, fTime);

>  толи callback функция должна быть, толи поток создать толи
> еще что?

Поток, конечно, д.б.
Например, он может WaitForSingleObject(hTimer, INFINITE)

--
Regards, LVT.


 
Dmitry_177   (2006-10-21 17:00) [7]

Посмотрите пожалуйста код, правильно ли он реализован? Вроде все работает, но правильно ли я закрываю хендл hTimer, а когда закрывать хендл hThread не знаю... Подскажите пожалуйста...


var
 hTimer: THandle;
 hThread: THandle;
 sysTime: TSystemTime;
 fTime: TFileTime;
 idThread: DWORD;

procedure WaitThread; stdcall;
begin
 WaitForSingleObject(hTimer, INFINITE);
 ShowMessage("Time!!!!!!!");
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 hTimer := CreateWaitableTimer(nil, false, nil);
   try
     GetLocalTime(sysTime);
     sysTime.wHour := 18;
     sysTime.wMinute := 0;
     sysTime.wSecond := 0;
     SystemTimeToFileTime(sysTime, fTime);
     LocalFileTimeToFileTime(fTime, fTime);
     SetWaitableTimer(hTimer, TLargeInteger(fTime), 0, nil, nil, false);

     hThread := CreateThread(nil, 0, @WaitThread, nil, 0, idThread);

     ShowMessage("Time installed!");
   finally
     CloseHandle(hTimer);
   end;
end;


 
GanibalLector ©   (2006-10-21 17:13) [8]

>когда закрывать хендл hThread
А сразу и закрывай...накой он тебе???
CloseHandle( CreateThread(nil, 0, @WaitThread, nil, 0, idThread));

> правильно ли я закрываю хендл hTimer
Хм...вопрос конечно интересный ;) Знаешь ли,есть только ОДНА ф-ция позволяющая закрывать обьекты ядра CloseHandle.
Далее...когда ее закрывать - это уже дело твое. Но,ОДНОЗНАЧНО не раньше, чем  WaitForSingleObject.


 
GanibalLector ©   (2006-10-21 17:15) [9]


var
hTimer: THandle;
hThread: THandle;
sysTime: TSystemTime;
fTime: TFileTime;
idThread: DWORD;


Я гляжу ты любитель глобальных переменных ;)


 
Leonid Troyanovsky ©   (2006-10-21 17:21) [10]


> Dmitry_177   (21.10.06 17:00) [7]

> Посмотрите пожалуйста код, правильно ли он реализован? Вроде
> все работает, но правильно ли я закрываю хендл hTimer, а
> когда закрывать хендл hThread не знаю...


Когда hTimer стал не нужен, тогда и закрывай.
Например, после WaitForSingleObject, т.е. в коде потока.

Аналогично - hThread, например, на месте ошибочного
CloseHandle(hTimer).
Кста, win32 функции исключений не генерируют, см. Win32Check.

Вообще-то, функция потока - это, все же, функция:
function WaitThread(p: Pointer): DWORD; stdcall;

И использовать там такие вещи, как ShowMessage - заказано.
Если уж приспичило - MessageBox.

--
Regards, LVT.


 
Dmitry_177   (2006-10-22 05:10) [11]

А вот так правильно будет? оба хендла (hTimer и hThread) закрываю в функции WaitThread после WaitForSingleObject. А если выключить программу (нажав на крестик) до срабатывания таймера, удалятся эти хендлы или их лучше в событии разрушения формы их удалять?


var
 hTimer: THandle;
 hThread: THandle;
 idThread: DWORD;

function WaitThread(Param: Pointer): DWORD; stdcall;
begin
 WaitForSingleObject(hTimer, INFINITE);
 CloseHandle(hTimer);    -> Правильно ли тут будет удалять хендл hTimer?
 CloseHandle(hThread);  -> Правильно ли тут будет удалять хендл hThread?
 MessageBox(0, "Time!!!!!!!", "Time", MB_OK);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 sysTime: TSystemTime;
 fTime: TFileTime;
begin
 hTimer := CreateWaitableTimer(nil, false, nil);
 GetLocalTime(sysTime);
 sysTime.wHour := 18;
 sysTime.wMinute := 0;
 sysTime.wSecond := 0;
 SystemTimeToFileTime(sysTime, fTime);
 LocalFileTimeToFileTime(fTime, fTime);
 SetWaitableTimer(hTimer, TLargeInteger(fTime), 0, nil, nil, false);

 hThread := CreateThread(nil, 0, @WaitThread, nil, 0, idThread);

 MessageBox(0, "Time installed!", "Time", MB_OK);
end;


 
Leonid Troyanovsky ©   (2006-10-22 10:21) [12]


> Dmitry_177   (22.10.06 05:10) [11]

> А вот так правильно будет? оба хендла (hTimer и hThread)
> закрываю в функции


Для закрытия хендлов есть одно правило: закрывать их в тот
момент, когда они стали более не нужны. Запускаемому потоку
собственный хендл не требуется ( в случае нужды он может
использовать GetCurrentThread). Т.к. первичный поток далее
нигде не использует hThread, то правильное место для закрытия -
сразу после CreateThread.

Кроме того, необходимо помнить, что глобальные переменные - зло.
Поэтому, idThread стоило бы переместить в ButtonClick (она, все равно,
нигде более не используется). Переменную hTimer также стоит
сделать локальной, а в функцию потока передать как параметр
CreateThread (.., @WaitThread, Pointer(hTimer), ..).

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

Хотя, если подобное происходит не с главной формой, то появляются
дополнительные трудности, для преодоления которых проще
воспользоваться классом TThread.

--
Regards, LVT.


 
GanibalLector ©   (2006-10-22 13:31) [13]


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 TForm1 = class(TForm)
   Exec: TButton;
   procedure ExecClick(Sender: TObject);
 private
   procedure Success( var Msg:TMessage); message WM_USER+1;
   { Private declarations }
 public
   { Public declarations }
 end;

type
 TMyMode = packed record
  hTimer,
  hMain:HWND;
 end;
 PMyMode = ^TMyMode;

var
 Form1: TForm1;

implementation

{$R *.DFM}

function WaitThread(Param: PMyMode): DWord;
begin
 WaitForSingleObject(Param.hTimer,INFINITE);
 CloseHandle(Param.hTimer);
 PostMessage(Param.hMain,WM_USER+1,0,0);
 Dispose(Param);
 Result:=0;
end;

procedure TForm1.ExecClick(Sender: TObject);
 var  sysTime: TSystemTime;
      fTime: TFileTime;
      ThreadID:DWord;
      Obj:PMyMode;
begin
 New(Obj);
 Obj^.hTimer:=CreateWaitableTimer(nil, false, nil);
 Obj^.hMain:=Handle;
 //
 GetLocalTime(sysTime);
 sysTime.wHour := 12;
 sysTime.wMinute := 31;
 sysTime.wSecond := 0;
 SystemTimeToFileTime(sysTime, fTime);
 LocalFileTimeToFileTime(fTime, fTime);
 SetWaitableTimer(Obj^.hTimer,TLargeInteger(fTime),0,nil,nil,False);
 //
 CloseHandle(BeginThread(nil, 0, @WaitThread, Obj, 0,ThreadID));
 MessageBox(0, "Time installed!", "Time", MB_OK);
end;

procedure TForm1.Success(var Msg: TMessage);
begin // вот тут и обращайся в VCL-контролам, формам и т.д.
 Windows.Beep(800,200);
 ShowMessage("Timer");
end;

end.


 
Dmitry_177   (2006-10-22 18:15) [14]

Спасибо, вы очень добры.. Если будет такая ситуация, ставим мы будильник на 18:00, а время будет уже больше 18:00, часов (19, 20, 21, 22, 23 например).. так вот день в sysTime, будет сегодняшний, а сработать таймер должен завтра, т.к. сегодня 18 часов уже было... Вот как прибавить к дате один день, с учетом того, что если день будет последним в текущем месяце, то 1-ый день будет следующего месяца, так же и с годом, если последний день года, т.е. 31 декабря...


 
Leonid Troyanovsky ©   (2006-10-22 18:28) [15]


> Dmitry_177   (22.10.06 18:15) [14]

>  сегодня 18 часов уже было... Вот как прибавить к дате один
> день, с учетом того, что если день будет последним в текущем
> месяце, то 1-ый день будет следующего месяца, так же и с
> годом, если последний день года, т.е. 31 декабря...


DateX := Date + 1;

--
Regards, LVT.


 
Dmitry_177   (2006-10-22 18:55) [16]

т.е. так?

GetLocalTime(sysTime);
if sysTime.wHour > 18 then
 sysTime.wDay := sysTime.wDay + 1;
sysTime.wHour := 18;
sysTime.wMinute := 0;
sysTime.wSecond := 0;


 
Leonid Troyanovsky ©   (2006-10-23 18:55) [17]


> Dmitry_177   (22.10.06 18:55) [16]

> т.е. так?


Огласи, плиз, причины неуверенности.
Хотя, конечно, мне ближе >=.

--
Regards, LVT.


 
Dmitry_177   (2006-10-23 20:40) [18]

Просто я никогда не работал с системным временем на API... Думал что тут надо все делать в ручную, т.е. проверять день (не последний ли он в текущем месяце и году) и т.д. Кстати мне тут подсказали вот такой код, интересно его лучше использовать или нет?

var
 sysTime: SYSTEMTIME;
 ft2: FILETIME;
begin
 { TODO -oUser -cConsole Main : Insert code here }
 GetLocalTime(sysTime);
 if sysTime.wHour >= 18 then
begin
//sysTime.wDay := sysTime.wDay + 1;
SystemTimeToFileTime(sysTime,ft2);
ft2.dwHighDateTime:=ft2.dwHighDateTime+201;
ft2.dwLowDateTime:=ft2.dwLowDateTime+ 711573504;
FileTimeToSystemTime(ft2,sysTime);
end;
sysTime.wHour := 18;
sysTime.wMinute := 0;
sysTime.wSecond := 0;
end.


 
Leonid Troyanovsky ©   (2006-10-23 20:46) [19]


> Dmitry_177   (23.10.06 20:40) [18]

>  Кстати мне тут подсказали вот такой код, интересно его
> лучше использовать или


А чего, очень даже прозрачно

> ft2.dwHighDateTime:=ft2.dwHighDateTime+201;
> ft2.dwLowDateTime:=ft2.dwLowDateTime+ 711573504;


Может в этом и есть сермяжная правда.

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

--
Regards, LVT.


 
Ketmar ©   (2006-10-23 20:48) [20]

>[18] Dmitry_177 23-Oct-2006, 20:40
>Кстати мне тут подсказали вот такой код
...с ошибкой. хинт: переполнение.


 
GanibalLector ©   (2006-10-24 01:28) [21]

2 Leonid Troyanovsky ©   (23.10.06 20:46) [19]

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

Чуть со стула не упал :))) Ржунамагу )))


 
Dmitry_177   (2006-10-24 11:19) [22]

Ketmar, подскажи пожалуйста где там ошибка?

А еще скажите пожалуйста, в коде GanibalLector ©   (22.10.06 13:31) [13] неужели лучше использовать сообщение? Т.е. программе передавать сообщение WM_USER+1 по сути дела самой себе.. Может лучше было бы просто вызвать процедуру Success в функции WaitThread? Если нет скажите пожалуста, мне это очень интересно знать...

Я как понял лучше использовать код Dmitry_177   (22.10.06 18:55) [16] чем Dmitry_177   (23.10.06 20:40) [18]?

Спасибо.


 
Ketmar ©   (2006-10-24 11:25) [23]

>[22] Dmitry_177 24-Oct-2006, 11:19
>Ketmar, подскажи пожалуйста где там ошибка?
а я уже подсказал. почитай [20] внимательно.


 
Dmitry_177   (2006-10-24 15:54) [24]

Ketmar я понял что переполнение, а чего? )))


 
Ketmar ©   (2006-10-24 17:29) [25]

>[24] Dmitry_177 24-Oct-2006, 15:54
>Ketmar я понял что переполнение, а чего? )))
ты не поверишь: переменных. на:
ft2.dwHighDateTime:=ft2.dwHighDateTime+201;
ft2.dwLowDateTime:=ft2.dwLowDateTime+ 711573504;

медитируй.


 
Dmitry_177   (2006-11-05 22:32) [26]

Почему код GanibalLector ©   (22.10.06 13:31) [13] с BeginThread работает код а с CreateThread нет? А еще зачем мы передаем сообщение WM_USER+1 из самой программы в нее же? Вот так нельзя сделать без сообщения?

function WaitThread(Param: PMyMode): DWord;
begin
WaitForSingleObject(Param.hTimer,INFINITE);
CloseHandle(Param.hTimer);
Windows.Beep(800,200);  //  Почему не тут эти строки там? Так же тоже работает...
ShowMessage("Timer");    //
Dispose(Param);
Result:=0;
end;



 
Ketmar ©   (2006-11-05 23:00) [27]

>[26] Dmitry_177 5-Nov-2006, 22:32
>Почему код GanibalLector ©  (22.10.06 13:31) [13] с
>BeginThread работает код а с CreateThread нет?
иди читать справку.


 
Орион ©   (2006-11-05 23:34) [28]

Dmitry_177, когда же мы твое творение увидим? или не увидим?)


 
Ketmar ©   (2006-11-06 00:03) [29]

лучше пусть не увидим...


 
Dmitry_177   (2006-11-06 00:16) [30]


> когда же мы твое творение увидим? или не увидим?)

))))
Ну так почему там не в WaitThread эти строки???:
Windows.Beep(800,200);
ShowMessage("Timer");

Мне же хочется знать и не задавать глупые вопросы.. И с
> BeginThread работает код а с CreateThread нет?

тоже самое...(((


 
Ketmar ©   (2006-11-06 00:19) [31]

>[30] Dmitry_177 6-Nov-2006, 00:16
>Мне же хочется знать и не задавать глупые вопросы.. И с
>> BeginThread работает код а с CreateThread нет?
>тоже самое...(((
таки ты не поверишь: для любознательных в Borland справку сочинили.


 
Dmitry_177   (2006-11-06 21:32) [32]

Искал я, всеже я не нашел разницы между BeginThread и CreateThread...


 
Орион ©   (2006-11-06 21:44) [33]

> [32] Dmitry_177   (06.11.06 21:32)


Видишь суслика? А он есть :)


 
Ketmar ©   (2006-11-06 22:05) [34]

>[32] Dmitry_177 6-Nov-2006, 21:32
>Искал я, всеже я не нашел разницы между BeginThread и
>CreateThread...
ищи дальше. попробуй, наконец, справку почитать, если ничего больше не помогло.


 
Dmitry_177   (2006-11-08 18:07) [35]

Почитал Рихтера, там рекомендуется использовать BeginThread а не  CreateThread... То что BeginThread создает защищенный поток и выделяет память под него и т.д... С этим вроде понятно... Но а зачем мы шлем сообщение WM_USER+1 из потока в программу? Почему нельзя выполнить этот код в процессе как показано в Dmitry_177   (05.11.06 22:32) [26]???


 
Ketmar ©   (2006-11-08 18:43) [36]

>[35] Dmitry_177 8-Nov-2006, 18:07
>Почитал Рихтера, там рекомендуется использовать
>BeginThread а не  CreateThread...
Рихтер уже о Delphi пишет? фигасе прогресс...

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


 
Dmitry_177   (2006-11-08 19:54) [37]


> Рихтер уже о Delphi пишет? фигасе прогресс...

Да не.. Я по C++ читал, но я как понял _BeginThreadEx из C++ это BeginThread в Delphi т.к. BeginThreadУч нету...
> потому что двойка тебе. это здесь столько раз обсуждали,
>  что повторять смысле не вижу.

жаль... может названия тем дадите хотябы или ссылки?


 
Ketmar ©   (2006-11-08 20:20) [38]

>[37] Dmitry_177 8-Nov-2006, 19:54
>Да не.. Я по C++ читал, но я как понял _BeginThreadEx из C+
>+ это BeginThread в Delphi т.к. BeginThreadУч нету...
плохо понял.

>жаль... может названия тем дадите хотябы или ссылки?
сколько платишь за поиск информации?


 
tesseract ©   (2006-11-09 18:00) [39]

Да и не забудь про то, что user-таймер в windows работает с точностью слепого стрелка - т.е с никакой, и изредка желательно проверять системное время.



Страницы: 1 вся ветка

Текущий архив: 2007.03.25;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.028 c
2-1172914538
Нуб
2007-03-03 12:35
2007.03.25
динамическое окно + динамическая кнопка


2-1173076282
Grover
2007-03-05 09:31
2007.03.25
Передача данных между приложениями.


2-1172907376
elserpiente
2007-03-03 10:36
2007.03.25
Что это?


15-1171568690
Johnmen
2007-02-15 22:44
2007.03.25
Что Вам мешает купить Windows?


8-1152533021
EV
2006-07-10 16:03
2007.03.25
32-битные изображения в Delphi