Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблема с таймером [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);
ты используешь оба варианта


Наверх

Титульная страница Поиск, карта сайта Написать письмо