![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблема с таймером [D7, WinXP]
incm © (2005-09-08 19:19:00)Есть:
hWnd := CreateWindow(sClassName, '', 0, 0, 0, 0, 0, 0, 0, hInstance, NIL);
tmr:=SetTimer(hWnd,1,20000,@OnTimer);
while GetMessage(Msg, 0, 0, 0) do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
KillTimer(hWnd,tmr);
Проблема в том, что функция OnTimer вызывается два раза подряд при срабатываниии таймера. Чего бы это могло быть?
Digitman (2005-09-09 16:12:00) [1]
> incm (09.09.05 16:02) [9]
> есть если я обрабатываю сообщения, то
.. то ты их должен обрабатывать. Не более того.
О том , кто и как вызовет твой обработчик, беспокоиться не нужно : от тебя требуется лишь вовремя вызывать DispatchMessage()
incm (2005-09-09 16:02:00) [2]То есть если я обрабатываю сообщения, то CallBack-функции быть не должно, а функцию я должен вызывать по сообщению WM_TIMER ?
Digitman (2005-09-09 14:37:00) [3]
> Игорь Шевченко © (09.09.05 14:12) [7]
угу.
с alertable state это я загнул.
Игорь Шевченко (2005-09-09 14:12:00) [4]Digitman © (09.09.05 14:02) [6]
> вместо этого в момент alertable state потока
В момент вызова функции DispatchMessage, если быть точным.
Digitman (2005-09-09 14:02:00) [5]
> Я так понял, что использование таймера так: SetTimer(0,1,20000,@OnTimer),
> возможно только в консольной проге?
неверно понял.
такое использование возможно в ЛЮБОЙ "проге".
> мне нужно создавать окно - у проги висит иконка в трее
на здоровье !
создавай хоть косой десяток окон - ничто этому не мешает и этио никак не связано с возможностями ф-ции SetTimer, которая позволяет отслеживать интервалы времени как при наличиии окон, так и в отсутствии оных в принципе
> в моем случае нужно только использовать обработку сообщения
> WM_TIMER ?
если ты указал hWnd заведомо существующего окна и указал последним параметром TimerProc = nil, то ты ОБЯЗАН обрабатывать сообщение WM_TIMER, ибо именно им таймер извещает тебя о наступлении события.
в противном случае (hWnd = 0 , TimerProc = адрес указанной тобой ф-ции) таймер при наступлении события не пошлет никакому окну сообщение WM_TIMER, вместо этого в момент alertable state потока, создавшего таймер, в его контексте будет вызвана та самая callback-ф-ция, адрес которой ты указал параметром TimerProc
alpet (2005-09-09 13:58:00) [6]incm (09.09.05 13:49) [4]
Значит не правильно понял :) Тебе надо в параметры SetTimer поглядеть, в справке они описаны детально.
Вот скажем модификация тест для GUI приложения:
1. Директиву $APPTYPE CONSOLE надо убрать
2. Вот код callback функции:
procedure TimerProc (nID, uMsg, dwUser, dw1, dw2: DWORD);
var time: SYSTEMTIME;
t: Text;
begin
GetLocalTime (time);
AssignFile (t, 'log.txt');
{$I-}
Append (t);
if IOresult <> 0 then ReWrite (t);
{$I+}
WriteLn (t, 'Event ', time.wHour, ':', time.wMinute, ':', time.wSecond);
CloseFile (t);
end; // Timer Proc
Вместо цикла сообщений (while) вставляется:
MessageBox (0, 'Test', 'Caption', MB_OK);
incm (2005-09-09 13:49:00) [7]Я так понял, что использование таймера так: SetTimer(0,1,20000,@OnTimer), возможно только в консольной проге?
Но мне нужно создавать окно - у проги висит иконка в трее.
Т.е. в моем случае нужно только использовать обработку сообщения WM_TIMER ?
alpet (2005-09-09 13:39:00) [8]
uses windows;
{$APPTYPE CONSOLE}
procedure TimerProc (nID, uMsg, dwUser, dw1, dw2: DWORD);
var time: SYSTEMTIME;
begin
GetLocalTime (time);
WriteLn ('Event ', time.wHour, ':', time.wMinute, ':', time.wSecond);
end;
var msg: tagMSG;
tmr: DWORD;
begin
tmr := SetTimer(0,0,5000,@TimerProc);
while GetMessage(Msg, 0, 0, 0) do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
KillTimer(0, tmr);
end.
По одному событию в 5 сек. Найди критическое отличие.
incm (2005-09-09 11:40:00) [9]SetTimer(0,1,20000,@OnTimer) - срабатывает всеравно два раза!
SetTimer(hWnd,1,20000,nil) - вообще не срабатывает - я не делал обработку события WM_TIMER.
Slym (2005-09-09 09:19:00) [10]SetTimer(hWnd,1,20000,@OnTimer);
Может срабатывать через:
1. сообщение WM_TIMER: SetTimer(hWnd,1,20000,nil);
2. через CallBack функцию SetTimer(0,1,20000,@OnTimer);
ты используешь оба варианта