Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторный практикум «Основы разработки приложений Windows» книга 2.DOC
Скачиваний:
91
Добавлен:
10.05.2014
Размер:
827.9 Кб
Скачать

Мультимедийные таймеры

Основным недостатком обычных таймеров Windows является невысокая предельная частота (18,2 Гц) и, как следствие этого, низкое временное разрешение (55 мс). Если воспользоваться таким таймером для плавного перемещения изображения какого-либо объекта по экрану, то при разрешении экрана 800600 пикселов объект затратит на прохождение всего экрана по горизонтали более 40 с, т. е. движение его будет чрезвычайно медленным. Для получения более высоких скоростей перемещения и для отсчета интервалов времени с более высокой точностью можно использовать мультимедийные таймеры, предельное разрешение которых составляет 1 мс, что соответствует частоте 1 кГц.

Для работы с мультимедийными таймерами предусмотрена небольшая группа специальных функций, имена которых начинаются со слова time(начинающегося со строчной буквы, что нетипично для имен функций Windows).

Рассмотрим несколько вариантов установки и использования мультимедийного таймера.

Измерение интервалов времени

В процессе оптимизации программ может возникнуть необходимость измерить время выполнения того или иного фрагмента программы. Для этого можно использовать мультимедийную функцию timeGetTime(), которая возвращает время в миллисекундах, истекшее от последней загрузки операционной системы:

DWORDt1,t2,t3;//Переменные для записи времени

t1=timeGetTime();

...//Контролируемый фрагмент программы

t2=timeGetTime();

t3=t2-t1;//Время выполнения контролируемого фрагмента в мс

Организация периодического процесса

Установка и использование мультимедийного таймера требует выполнения целого ряда действий. Прежде всего с помощью функции timeBeginPeriod()задается требуемое временное разрешение устанавливаемого таймера в миллисекундах. Хотя минимальное значение параметра этой функции составляет 1 мс, однако следует иметь в виду, что установленный таймер активно использует ресурсы операционной системы и при малом значении времени разрешения или при установке нескольких таймеров системе может не хватить ресурсов, что приведет к ее аварийной остановке.

Следующим этапом является установка временного события, которая выполняется с помощью функции timeSetEvent(). В качестве параметров этой функции указывается, в частности, временной интервал срабатывания таймера, а также адрес той прикладной функции обратного вызова, которая будет активизироваться при каждом его срабатывании.

Уничтожение мультимедийного таймера требует вызова двух функций: timeEndPeriod(), отменяющей установленное ранее разрешение таймера, иtimeKillEvent(), которая прекращает действие всех системных процессов, связанных с работой мультимедийного таймера.

Фрагмент программы, в которой устанавливается мультимедийный таймер, может выглядеть таким образом:

timeBeginPeriod(1);//Установим максимальное разрешение

MMRESULT mmr=timeSetEvent(5,1,TimeProc,0,TIME_PERIODIC);

...//Продолжение программы

В качестве параметров функции timeSetEvent()указывается период его срабатывания (5 мс в примере), значение установленного ранее разрешения (1 мс), имя прикладной функции обработки прерываний от таймера (например,TimeProc), произвольное данное пользователя, которое будет передано в эту функцию (у нас 0), а также символическая константа, задающая режим работы таймера. Функция установки таймера возвращает (в переменную типаMMRESULT) его номер, назначаемый системой и используемый затем нами при уничтожении данного таймера.

Прикладная функция TimeProc(), вызываемая в данном примере каждые 5 мс, предназначена для выполнения требуемых периодических действий. Сложность, однако, заключается в том, что в этой функции запрещен вызов каких-либо функций Windows, кроме мультимедийных, а также функцииPostQuitMessage(). В результате типичный текст функцииTimeProc()выглядит сле­дующим образом:

void CALLBACK TimeProc(UINT,UINT,DWORD,DWORD,DWORD){

PostMessage(hwnd,WM_USER,(WPARAM)parm1,(LPARAM)parm2);

}

Вызов функции PostMessage()приводит к посылке в окноhwndнашего приложения сообщения пользователя с кодомWM_USER, в состав которого входят два произвольных параметраparm1иparm2. Для Windows кодWM_USER(он равен 0x400), при использовании его в рамках окон прикладных классов, ничего не значит, так как стандартные сообщения Windows имеют коды от 0 доWM_USER–1, однако мы можем обрабатывать сообщениеWM_USERв нашей оконной функции наравне с остальными (системными) сообщениями:

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,

WPARAM wParam,LPARAM lParam){

switch(msg){

HANDLE_MSG(hwnd,WM_CREATE,OnCreate);

HANDLE_MSG(hwnd,WM_PAINT,OnPaint);

HANDLE_MSG(hwnd,WM_DESTROY,OnDestroy);

... //Обработка других сообщений Windows

default:

return(DefWindowProc(hwnd,msg,wParam,lParam));

case WM_USER:

OnUser(wParam,lParam);//Вызов прикладной функции

//обработки сообщений от мультимедийного таймера

}

}

На выполнение прикладной функции OnUser(), которой через ее аргументыwParamиlParamпередаются (при необходимости) наши параметрыparm1иparm2, уже не накладывается никаких ограничений; в ней можно выполнять любые действия и, в частности, вызывать любые функции Windows. Следует только иметь в виду, что функцияOnUser()не вызывается непосредственно прерыванием от таймера; сообщениеWM_USERпоступает в очередь сообщений приложения, а функцияOnUser()будет вызвана, лишь когда дойдет очередь до обработки этого сообщения. Описанный здесь механизм иногда называют отсроченной или отложенной обработкой.

После того, как необходимость в периодических действиях отпала, мультимедийный таймер необходимо уничтожить:

timeEndPeriod(1);//Указывается заданное ранее разрешение

timeKillEvent(mmr);//Указывается номер данного таймера