Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.03.12;
Скачать: [xml.tar.bz2];

Вниз

TimerProc дважды   Найти похожие ветки 

 
Дубинка   (2006-02-24 15:18) [0]

Глупый наверное вопрос. Я создаю таймер:
id := SetTimer(0, 0, 1000, @TimerProc);

Однако эта процедура:
procedure TimerProc(wnd: HWND; uMsg: Integer; idEvent: Integer; dwTime: DWORD);
begin
{.....}
end;
вызывается через каждую секунду два раза подряд. причем в первом случае
idEvent = 0, а во втором wnd = 0, мне интересно, как от этого избавиться...
Вроде бы надо Dispatch"ить сообщение, только не знаю как это сделать.


 
umbra ©   (2006-02-24 15:24) [1]

при вызове SetTimer в первом параметре стоит указывать окно, к которому таймер относится
id := SetTimer(hwnd, 0, 1000, @TimerProc);


 
Дубинка   (2006-02-24 15:27) [2]

бывает так что нет окна. К примеру, если функция вызывается из dll смысл в создании окла не то что нулевой, а вообще отрицательный. Да и в справке указано:
hWnd [in] Handle to the window to be associated with the timer. This window must be owned by the calling thread. If this parameter is NULL, no window is associated with the timer and the nIDEvent parameter is ignored.
То бишь может быть нулем.


 
umbra ©   (2006-02-24 15:50) [3]

так не надо ничего создавать. Из ДЛЛ функцию вызывает какое-то приложение, у которого есть окно. Вот его hwnd и надо передавать в SetTimer. Процесс диспетчеризации сообщения WM_TIMER и заключается в том, что указывается хендл окна, которому это сообщение нужно.


 
Дубинка   (2006-02-24 17:04) [4]

ладно, указал я хэндл какого-то окна, все равно два раза вызывается.


 
begin...end ©   (2006-02-24 17:06) [5]

> Дубинка   (24.02.06 15:18)

> вызывается через каждую секунду два раза подряд.

Полный код можно увидеть?

> в первом случае
> idEvent = 0, а во втором wnd = 0


На параметры можно пока не обращать внимание, т.к. у TimerProc не указано нужное соглашение о вызове (stdcall). Исправьте.

> Вроде бы надо Dispatch"ить сообщение, только не знаю как
> это сделать.


А в каком потоке таймер устанавливается? В главном потоке-то цикл выборки сообщений обычно уже есть :)

Вообще, если таймер создаётся без указания окна, то при "срабатывании" таймера происходит следующее:

1. В очередь потока, создавшего таймер, ставится сообщение WM_TIMER.
2. Если в потоке работает цикл выборки сообщений (GetMessage), и в этом цикле вызывается DispatchMessage, это сообщение выбирается из очереди и передаётся в DefWindowProc.
3. DefWindowProc вызывает указанную при создании таймера callback-функцию.

Т.е. разница между созданием таймера с указанием окна и без оного -- в том, что в первом случае WM_TIMER будет приходить в оконную процедуру указанного окна, а во втором случае -- в дефолтную оконную процедуру. И в обоих случаях, конечно, нужен цикл диспетчеризации сообщений.


 
Дубинка   (2006-02-24 17:23) [6]

На параметры можно пока не обращать внимание, т.к. у TimerProc не указано нужное соглашение о вызове (stdcall). Исправьте.

Точно! А я даже и не обратил внимания. Не будете любезны объяснить мне? Я кажется отдаленно понимаю. Вроде по умолчанию стоит register, и параметры передаются слева направо, а должны наоборот. Только почему из-за этого функция дважды вызывается?


 
Дубинка   (2006-02-24 17:25) [7]

Если оставить значимую часть в коде, остается это:

library gccore;

uses SysUtils, Windows;

var i: Integer;

procedure TimerProc(wnd: HWND; uMsg, idEvent: Integer; dwTime: DWORD);stdcall
begin
 Inc(i);
 TextOut(GetDC(0), 0,0, Pchar(inttostr(i)), 3);
end;

begin
 SetTimer(0, 0, 1000, @TimerProc);
end.

И где здесь должен быть цикл обработки сообщений?


 
umbra ©   (2006-02-24 17:51) [8]


> И где здесь должен быть цикл обработки сообщений?
>


в приведенном Вами коде - нигде. библиотека не работает сама по себе. ее использует какое-то приложение.


 
begin...end ©   (2006-02-24 17:59) [9]

> Дубинка   (24.02.06 17:23) [6]

Да, по умолчанию стоит register. Это означает, что перед вызовом подпрограммы первые три параметра передаются через регистры процессора, а оставшиеся -- через стек (причём вначале в стек помещается самый "левый" из оставшихся параметров, затем -- следующий, и т.д.). Это соглашение означает также и то, что подпрограмма сама должна удалять из стека переданные ей параметры.

А если указано stdcall, то ВСЕ параметры передаются через стек (причём справа налево: сначала последний, потом предпоследий, и т.д.). И в этом случае тоже за очистку стека отвечает сама подпрограмма.

Система, рассчитывая на то, что функция объявлена с соглашением stdcall, перед вызовом TimerProc передаёт все четыре параметра через стек, и надеется, что он будет правильно очищен вызываемой процедурой. Но TimerProc была объявлена с соглашением register, и она удалит из стека только один параметр, т.к. её код сгенерирован в расчёте на то, что первые три параметра ей переданы через регистры. В результате стек балансируется неправильно, а это может повлечь за собой самые разнообразные чудеса.

> Дубинка   (24.02.06 17:25) [7]

Здесь -- не нужен. Цикл уже есть (в том потоке, в контексте которого вызывается SetTimer), иначе вызова TimerProc не происходило бы.


 
umbra ©   (2006-02-24 18:41) [10]

по логике, если TimerProc вызывается дважды, значит на сообщение WM_TIMER реагируют дважды. Один раз реагирует сам сама TimerProc, а второй - какая-то оконная процедура.


 
begin...end ©   (2006-02-24 20:23) [11]

Сорри, насчёт DefWindowProc в [5] -- эт я фигню какую-то сморозил. Меня чего-то MSDN с толку сбила: "When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER". DefWindowProc, вроде, ни при чём -- callback вызывает сама DispatchMessage.

Уж простите дурака :)


 
Дубинка   (2006-02-24 20:27) [12]

Все. Мне все понятно. Благодарю!



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

Форум: "Начинающим";
Текущий архив: 2006.03.12;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.014 c
1-1138965725
krush
2006-02-03 14:22
2006.03.12
Как убрать показ "Панель управления" в ShellTreeView


2-1140886598
Radagast
2006-02-25 19:56
2006.03.12
Invalid floating point operation


3-1134517618
alpine
2005-12-14 02:46
2006.03.12
Выборка из 10 и более таблиц Paradox


11-1121302017
stals
2005-07-14 04:46
2006.03.12
exe-шник (? kb)


2-1140788428
Golik
2006-02-24 16:40
2006.03.12
Сортировка в DBGride ??





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский