- •Лабораторный практикум «Основы разработки приложений Windows» Книга 2
- •Часть 1. Теоретические сведения4
- •Часть 2. Лабораторный практикум73
- •Часть 1 Теоретические сведения
- •1. Основы архитектурЫ защищенного режима Регистры процессора
- •Адресация памяти
- •2. Логические шрифты Создание логических шрифтов
- •Вывод на экран текстовых строк
- •3. Таймеры Windows Организация и обслуживание таймеров
- •Мультимедийные таймеры
- •Измерение интервалов времени
- •Организация периодического процесса
- •Задание однократного интервала времени
- •4. Дочерние окна Создание и использование дочерних окон
- •Окна предопределенных классов в главном окне
- •5. Вывод растровых изображений
- •Процедура вывода растрового изображения
- •Компоновка составных изображений
- •6. Обслуживание файлов в 32-разрядных приложениях Windows
- •Базовые операции с файлами Открытие и создание файла
- •Запись и чтение файла
- •Файлы, проецируемые в память
- •7. Процессы и потоки
- •Создание дочернего процесса
- •Создание дочернего потока
- •Синхронизация потоков Общие характеристики объектов Windows
- •Синхронизация с помощью состояний потока
- •Синхронизация с помощью событий
- •Критические секции и защита данных
- •8. Библиотеки динамической компоновки
- •Часть 2 Лабораторный практикум Работы лабораторного практикума Работа 1. Создание логических шрифтов
- •Работа 2. Таймеры Windows(индивидуальное задание а)
- •Работа 3. Дочернее окно в главном окне приложения
- •Работа 4. Вывод растровых изображений с использованием совместимой памяти
- •Работа 5. Измерение временных характеристик программы с помощью мультимедийного таймера
- •Работа 6. Вывод движущихся изображений с синхронизацией от системного таймера (индивидуальное задание b)
- •Работа 7. Повышение качества движущихся изображений с помощью совместимой памяти
- •Работа 8. Движение изображения по фоновому рисунку
- •Работа 9. Работа с файлами (индивидуальное задание c)
- •Работа 10. Стандартные диалоги Windows для работы с файлами
- •Работа 11. Проецирование файла в память
- •Работа 12. Потоки (индивидуальное задание d)
- •Работа 13. Синхронизация потоков с помощью событий
- •Работа 14. Защита данных с помощью критической секции
- •Работа 15. Библиотеки динамической компоновки
- •Работа 16. Передача параметров в функции dll-библиотек
- •Индивидуальные задания лабораторного практикума
- •Задание c2.Массив записываемых в файл данных должен представлять собой последовательный ряд из 2000 целых четных чисел.
- •Лабораторный практикум «Основы разработки приложений Windows» Книга 2
Мультимедийные таймеры
Основным недостатком обычных таймеров Windows является невысокая предельная частота (18,2 Гц) и, как следствие этого, низкое временное разрешение (55 мс). Если воспользоваться таким таймером для плавного перемещения изображения какого-либо объекта по экрану, то при разрешении экрана 800600 пикселов объект затратит на прохождение всего экрана по горизонтали более 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);//Указывается номер данного таймера