Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Программирование на WinApi, C++Builder, Visual C++


Информационный Канал Subscribe.Ru


Выпуск № 22-2003 BCBDEV.RU

Здравствуйте уважаемые подписчики!

Перед вами очередной выпуск рассылки "Программирование на 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. Например:

#define WM_DATAMSG WM_USER+1
HWND hGlobalWnd;
...
или hGlobalWnd=Handle; или hGlobalWnd=GetSafeHwnd();
...
void CALLBACK CallBackDo( UINT , UINT , DWORD , DWORD , DWORD )
{
SendMessage(hGlobalWnd,WM_DATAMSG ,(WPARAM)данные , (LPARAM)данные);
}

Надеюсь как обрабатывать полученное сообщение известно.

Q: Не могли бы вы дать краткое описание полей функций TimeProc, timeSetEvent, timeKillEvent .
A: Берем описание из MSDN, попутно его переводим, и поясняем значения полей .

MMRESULT timeSetEvent(
  UINT uDelay,
  UINT uResolution,
  LPTIMECALLBACK lpTimeProc,
  DWORD_PTR dwUser,
  UINT fuEvent
);
uDelay - Этот параметр определяет период срабатывания таймера в миллисекундах.
uResolution - Определяет разрешение таймера. Чем ниже этот параметр, тем события вызываемые таймером будут происходить чаще. Если вам нет необходимости сильно перегружать систему ставьте этот параметр в районе 10, если выставить 0, то события будут происходить с максимально возможной частотой. Примерно то же самое, что и приоритеты процессов.
lpTimeProc - Процедура обратного вызова. Используется для осуществления таймером, какой либо полезной работы.
dwUser - Этот параметр может быть произвольным числом. О нем будет сказано ниже, так как довольно большая часть написавших интересовалась назначением этого параметра.
fuEvent - об этом параметре было сказано в предыдущей рассылке.
MMRESULT timeKillEvent(
  UINT uTimerID
);

uTimerID - Идентификатор таймера, который требуется остановить. Идентификатор может быть получен путем вызова функции timeSetEvent. Некоторых это ввело в заблуждение, так как то, что возвращает одна функция и принимает другая имеет разные типы. Не стоит обращать внимание на сей факт. Почему дядя Билли решил наваять это именно так, остается загадкой.

void
CALLBACK TimeProc(
    UINT  uID,
    UINT  uMsg,
    DWORD dwUser,
    DWORD dw1,
    DWORD dw2 );
uID - Идентификатор события таймера. Идентификатор получается путем вызова функции timeSetEvent.
dwUser - Этот параметр может быть произвольным числом.
Остальные члены данной функции зарезервированы для будущего использования.

Q: Обязательно ли уничтожать таймеры созданные функцией timeSetEvent ?
A: Обязательно только для периодических таймеров. Разовые таймеры уничтожать не требуется.

Q: Для чего используется параметр dwUser.
A: У этого параметра как много применений, так и ни одного. Другими словами вы можете его использовать, а можете и не использовать. Рассмотрим такой пример. Вам требуется что то передать в функцию обратного вызова таймера. Именно для этого и может использоваться данный параметр. В основном это используется для того, чтобы не замусоривать глобальными переменными память.
 

Удачи Вам в Ваших делах Куковинец Андрей aka Juggernaut

http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное