Перед вами
очередной выпуск рассылки "Программирование на WinApi" Переводы многих функций Win32API, которые часто используются
в данной рассылке, вы можете получать, подписавшись на дружественную
рассылку "WinAPI на
русском". Справочник по функциям Win32API вы
можете посмотреть на сайте BcbDev.ru в разделе MSDN
по-русски.
Создание
таймеров
2
Ну вы народ даете. Заглянул сегодня в ящик и
обалдел. Думал спамом завалили, ошибся. Пришло более 30 писем по поводу таймеров. Посему небольшое продолжение.
Так как смысл писем был примерно одинаков, рассылка будет представлять
собой небольшую справку по таймерам и заодно являться ответами на ваши
вопросы. Сильно извиняюсь перед теми, кому не успел ответить. Надеюсь после
этого выпуска вопросы, по этой теме, по большей части отпадут.
Ну а если не отпадут, напишите заново, постараюсь ответить на этот
раз всем.
Итак, поехали. Q: Почему вы
считаете, что использовать такой таймер лучше, чем использовать обычный
таймер. A: Таймеры такого вида называются
мультимедийными не так просто. Таймеры такого типа позволяют вести более
точный отсчет времени, чем обычные, и применяются в мультимедийных
приложениях. У обычных таймеров максимальная разрешающая способность не
может превысить порог в 55 мс. У таймеров мультимедийного типа
разрешающая способность 1 мс. Так как обычный таймер зависит от аппаратной
реализации компьютера, то и разрешение у него не может быть выше, чем
аппаратное. А аппаратное разрешение таймера не может быть выше, чем 55 мс.
Хотелось бы заметить, что компонентная реализация таймера VCL основана
именно на аппаратном таймере.
Q: Обязательно ли создавать для мультимедийных
таймеров окна? A: Нет не обязательно. Таймер
можно создавать даже в функции WinMain без создания, какого либо
графического интерфейса
.
Q: Как мне из процедуры обратного вызова таймера
послать сообщение главному окну приложения? A: Если вы создаете таймер
где-то в классе, отвечающем за создание окна, вы можете получить
дескриптор этого окна, и объявить глобальную переменную типа HWND, равную
полученному дескриптору. Например, в C++Builder VCL это просто Handle ну
или если не искать легких путей this->Handle. В MFC это может быть
GetSafeHwnd(). Далее вам надо определить какое либо сообщение,
которое будет получать окно, и именно это сообщение посылать через функцию
SendMessage.
Например:
Надеюсь как обрабатывать полученное сообщение
известно.
Q: Не могли бы вы дать краткое описание полей функций TimeProc,
timeSetEvent, timeKillEvent
. A: Берем описание из MSDN, попутно его переводим, и поясняем
значения полей
.
uDelay - Этот параметр определяет период
срабатывания таймера в миллисекундах. uResolution -
Определяет
разрешение таймера. Чем ниже этот параметр, тем события вызываемые
таймером будут происходить чаще. Если вам нет необходимости сильно
перегружать систему ставьте этот параметр в районе 10, если выставить
0, то события будут происходить с максимально возможной частотой.
Примерно то же самое, что и приоритеты
процессов. lpTimeProc - Процедура обратного вызова.
Используется для осуществления таймером, какой либо полезной
работы. dwUser - Этот параметр может быть произвольным
числом. О нем будет сказано ниже, так как довольно большая часть написавших
интересовалась назначением этого параметра. fuEvent -
об этом параметре было сказано в предыдущей рассылке.
MMRESULT timeKillEvent(
UINT uTimerID
);
uTimerID - Идентификатор
таймера, который требуется остановить. Идентификатор может быть
получен путем вызова функции timeSetEvent. Некоторых это ввело в
заблуждение, так как то, что возвращает одна функция и принимает другая
имеет разные типы. Не стоит обращать внимание на сей факт. Почему
дядя Билли решил наваять это именно так, остается
загадкой.
uID - Идентификатор события таймера. Идентификатор
получается путем вызова функции timeSetEvent. dwUser -
Этот параметр может быть произвольным числом. Остальные члены данной
функции зарезервированы для будущего использования.
Q: Обязательно ли уничтожать таймеры созданные функцией
timeSetEvent ? A: Обязательно только для
периодических таймеров. Разовые таймеры уничтожать не
требуется.
Q: Для чего используется
параметр dwUser. A: У этого параметра как
много применений, так и ни одного. Другими словами вы можете его
использовать, а можете и не использовать. Рассмотрим такой пример. Вам
требуется что то передать в функцию обратного вызова таймера. Именно для
этого и может использоваться данный параметр. В основном это
используется для того, чтобы не замусоривать глобальными переменными
память.