- •Лабораторный практикум «Основы разработки приложений 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
Запись и чтение файла
При работе с данными, содержащимися в файле, чаще других используются три функции: записи в файл WriteFile(), чтения из файлаReadFile() и установки файлового указателяSetFilePointer().
Функции чтения и записи имеют практически одинаковые прототипы:
BOOL ReadFile(HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped);
BOOL WriteFile(HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped);
Параметр hFileобозначает полученный от функцииCreateFile()дескриптор созданного или открытого файла.
Параметр lpBufferпредставляет собой адрес программного буфера, предназначенного для хранения данных, записываемых в файл или считываемых из файла. Обобщенный тип этого буфера –LPVOIDилиLPCVOID– позволяет обмениваться с файлом данными любой организации – отдельными байтами или скалярными переменными большей длины, а также массивами и структурами.
Третий параметр рассматриваемых функций определяет заказываемый объем пересылаемых данных (в байтах).
Четвертый параметр является адресом программной переменной типа DWORD, в которую после завершения передачи данных будет записано истинное число переданных байтов. Этой переменной можно воспользоваться для контроля правильности выполненной операции записи или чтения.
Последний параметр, lpOverlapped, используется в тех случаях, когда операции над файлом предполагается осуществлять в асинхронном режиме (его еще называют режимом с перекрытием). Обычно программа, поставив запрос на чтение данных из файла или запись данных в файл, останавливается до завершения этой операции, хотя в течение всего этого времени процессор почти свободен и мог бы выполнять полезную работу. Такой режим выполнения программы называется синхронным. Некоторые операционные системы, в частности, WindowsNTи Windows 2000, позволяют выполнять асинхронные операции над файлами. Суть асинхронного режима заключается в том, что система, запустив операцию ввода или вывода, возвращает управление в программу, которая может таким образом продолжить выполнение параллельно с дисковой операцией ввода-вывода. В случае обычных операций чтения или записи значение параметраlpOverlappedдолжно быть равноNULL.
Функция SetFilePointer()установки файлового указателя служит для перемещения указателя в файле на заданный байт, чтобы последующая операция чтения или записи выполнила пересылку данных не с начала файла, а от положения указателя. Прототип этой функции имеет следующий вид:
DWORD SetFilePointer(HANDLE hFile,LONG lDistanceToMove,
PLONG lpDistanceToMoveHigh,DWORD dwMoveMethod);
Параметр hFileобозначает полученный от функцииCreateFile()дескриптор созданного или открытого файла.
Параметр lDistanceToMoveзадает 32-битовое смещение в файле до точки установки указателя.
Параметр lpDistanceToMoveHighявляется адресом старшей половины смещения указателя, если смещение характеризуется 64-битовым значением. Обычно здесь указываетсяNULL.
Последний параметр dwMoveMethodопределяет способ установки указателя. Этот параметр может принимать три значения:
FILE_BEGIN– указатель устанавливается от начала файла и, следовательно, рассматривается как число без знака. Максимальное смещение в файле (если не использовать параметрlpDistanceToMoveHigh) достигает 232 - 2 = 4 Гбайт - 2;
FILE_CURRENT– указатель устанавливается от текущей позиции указателя и, следовательно, рассматривается как число со знаком, что позволяет смещать указатель как вперед, так и назад от текущего положения в пределах до 2 Гбайт;
FILE_END– указатель устанавливается от конца файла, причем смещение может быть как положительным, так и отрицательным.
Рассмотрим содержательную часть простой программы, создающей новый файл, записывающей в него некоторую информацию, а затем выполняющей, с целью контроля, чтение небольшой порции этой информации:
struct GOODS{//Структура, описывающая изделия на складе
int Nmb;//Номер изделия
int Price;//Цена изделия
};
const int N=1000000;//Пусть на складе миллион образцов изделий
GOODS Stock[N];//Создадим в памяти массив для всех изделий
GOODS Unit1;//Структурная переменная для одного изделия
DWORD dwCount;//Для функций чтения/записи
... //Заполним массив структур данными
/*Создадим новый файл*/
HANDLE hFile=CreateFile("stock.dat",
GENERIC_READ|GENERIC_WRITE,
0,NULL,CREATE_ALWAYS,0,NULL);
/*Запишем в файл весь массив структурных переменных*/
WriteFile(hFile,Stock,sizeof(Stock),&dwCount,NULL);
/*Сместим указатель на последнюю записьи прочитаем ее*/
SetFilePointer(hFile,sizeof(GOODS)*(-1),NULL,FILE_END);
ReadFile(hFile,&Unit1,sizeof(GOODS),&dwCount,NULL);
CloseHandle(hFile);//Закроем файл (нет необходимости)
С таким же успехом и даже более наглядно было бы в операциях записи, установки указатели и чтения указывать количество записываемых байтов в виде числа. Поскольку каждое число типа intтребует для своего хранения четыре байта, то каждая структурная переменная типаGOODSзанимает в памяти 8 байт, а весь массив – 8000000 байт. Поэтому запись в файл можно выполнить таким образом:
WriteFile(hFile,Stock,8000000,&dwCount,NULL);
а, например, установку указателя так:
SetFilePointer(hFile, -8,NULL,FILE_END);
или так:
SetFilePointer(hFile, 7999992,NULL,FILE_BEGIN);
Следует заметить, что при работе с большими массивами (превышающими по объему 1 Мбайт) надо специально подумать об их размещении в памяти. Если массив объявлен как локальная переменная, то для него должно быть выделено место в стеке, а размер стека по умолчанию ограничивается системой программирования. Впрочем, изменив настройки системы программирования, можно увеличить стек до нужного размера.