Курсовая работа: Программирование графического режима
Модель памяти также коренным образом отличается от 16-битных программ. Под Win32 мы больше не должны беспокоиться о моделях памяти или сегментах. Теперь только одна модель память: плоская, без 64-ти килобайтных сегментов. Теперь память - это большое последовательное 4-х гигабайтовое пространство. Это также означает, что не нужно работать с сегментными регистрами, зато можно использовать любой сегментный регистр для адресации к любой точке памяти. Это ОГРОМНОЕ подспорье для программистов. Это то, что делает программирование на ассемблере под Win32 таким же простым, как на C.
1.3.2. Использование Win32 API
Windowsпредоставляет огромное количество ресурсов Windows-программам через Windows API (ApplicationProgrammingInterface). Windows API - это большая коллекция очень полезных функций, располагающихся непосредственно в операционной системе и готовых для использования программами. Эти функции находятся в нескольких динамически подгружаемых библиотек, таких как kernel32.dll , user32.dll, gdi32.dll и т.д . Kernel32.dll содержит API функции, взаимодействующие с памятью и управляющие процессами. User32.dll контролирует пользовательский интерфейс. Gdi32.dll ответственен за графические операции. Кроме этих трех "основных", существуют также другие динамические библиотеки, которые можно использовать при условии, что обладаете достаточным количеством информации о нужных API функциях. Windows-программы динамически подсоединяются к этим библиотекам, то есть код API функций не включается в исполняемый файл. Информация находится в библиотеках импорта. Нужно слинковать программы с правильными библиотеками импорта, иначе они не смогут найти эти функции. Когда Windows-программа загружается в память, Windows читает информацию, сохраненную в программе. Эта информация включает имена функций, которые программа использует и DLL-ок, в которых эти функции располагаются. Когда Windows находит подобную информацию в программе, она вызывает библиотеки и исправляет в программе вызовы этих функций, так что контроль всегда будет передаваться по правильному адресу.
Существует две категории API функций: одна для ANSI и другая для Unicode. На конце имен API функций для ANSI стоит "A", например, MessageBoxA. В конце имен функций для Unicode находится "W”. Мы обычно имеем дело с ANSI строками (массивы символов, оканчивающиеся NULL-ом). Размер ANSI-символа - 1 байт. В то время как ANSI достаточна для европейских языков, она не поддерживает некоторые восточные языки, в которых есть несколько тысяч уникальных символов. Вот в этих случаях в дело вступает Unicode. Размер символа UNICODE - 2 байта, и поэтому может поддерживать 65536 уникальных символов. Но по большей части, используются include-файлы, которые могут определить и выбрать подходящую для платформы функцию. Тогда достаточно обращаться к именам API функций без постфикса.
1.3.3. Основы рисования
С точки зрения программиста Windows является системой, не зависящей от устройств (deviceindependent). Эту независимость со стороны Windows обеспечивает библиотека GDI32.dll, а со стороны устройства - драйвер этого устройства. С точки зрения программы связующим звеном между программой и устройством является контекст устройства (DeviceContext - DC). Если программе нужно осуществить обмен с внешним устройством, программа должна оповестить GDI о необходимости подготовить устройство для операции ввода-вывода. После того, как устройство подготовлено, программа получает хэндл контекста устройства, т. е. хэндл структуры, содержащей набор характеристик этого устройства. В этот набор входят:
1. bitmap (битовая карта, изображение), отображаемый в окне
2. перо для прорисовки линий
3. кисть
4. палитра
5. шрифт
и т. д. Программа никогда напрямую не обращается к контексту устройства (кстати, эта структура не документирована Microsoft), она обращается к нему опосредствованно, через определенные функции. После того, как все действия произведены, и необходимость в использовании устройства отпала, программа должна освободить контекст устройства, чтобы не занимать память. Есть еще одна причина, из-за которой необходимо освобождать контекст устройства. В системе может существовать одновременно только ограниченное число контекстов устройств. Если контекст устройства не будет освобождаться после операций вывода, то через несколько перерисовок окна система может зависнуть.
Когда программа требует контекст устройства, она получает его уже заполненным значениями по умолчанию. Объект в составе контекста называется текущим объектом. Само слово – текущий – говорит о том, что контекст устройства можно изменить. Программа может создать новый объект, скажем, bitmap или шрифт, и сделать его текущим. Замещенный объект автоматически из памяти не удаляется и его необходимо позже удалить отдельно. Само собой разумеется, что программа может получить характеристики текущего устройства. А вот изменить эти характеристики, увы, можно только через замену объекта (впрочем, это и так понятно).
В Windows поддерживаются следующие типы контекстов устройств:
1. контекст дисплея (обеспечивает работу с дисплеем)
2. контекст принтера (обеспечивает работу с принтером)
3. контекст в памяти (моделирует в памяти устройство вывода)
4. информационный контекст (служит для получения данных от устройства)
Windows поддерживает три типа контекста дисплея - контекст класса, приватный контекст и общий контекст. Первые два типа используются в приложениях, которые выводят на экран большое количество информации. Ярким примером такого рода приложений являются настольные издательские приложения, графические пакеты и т.д.
Приложения, которые не очень интенсивно работают с экраном, используют общий контекст. Контекст класса является устаревшим и поддерживается только для обеспечения совместимости с предыдущими версиями Windows. Microsoft не рекомендует использовать его при разработке новых приложении и рекомендует использовать только приватный контекст.
Контексты устройств хранятся в кэше, управляемом системой. Хэндл общего контекста программа получает с помощью функций GetDC, GetDCEx или BeginPaint. После того, как программа отработает с дисплеем, она должна освободить контекст, вызвав функцию ReleaseDCили EndPaint (в случаи, если контекст получался с помощью BeginPaint). После того, как контекст дисплея освобожден, все изменения, внесенные в него программой, теряются и при повторном получении контекста все действия по изменению контекста необходимо повторять заново.
Приватный контекст отличается от общего тем, что сохраняет изменения даже после того, как прикладная программа освободила его. Приватный контекст не хранится в кэше, поэтому прикладная программа может не освобождать его. Естественно, что в этом случае за счет использования большого объема памяти достигается более высокая скорость работы с дисплеем.
Для работы с приватным контекстом необходимо при регистрации класса окна указать стиль CS_OWNDC. После этого программа может получать хэндл контекста устройства точно так же, как и в случае общего контекста. Система удаляет приватный контекст в том случае, когда удаляется окно.
При работе с контекстами необходимо запомнить, что хэндлы контекста устройства с помощью функции BeginPaint необходимо получать только в случае обработки сообщения WM_PAINT. Во всех остальных случаях необходимо использовать функции GetDC или GetDCEx.
Контекст в памяти используется для хранения изображений, которые затем будут скопированы на устройство вывода. Сам по себе контекст в памяти не создается. Он обязательно создан как совместимый с тем устройством или окном, на которое предполагается копировать информацию (вот он - совместимый контекст - переходник между программой и драйвером устройства!). Алгоритм работы с контекстом в памяти состоит из нескольких шагов:
1. Получения хэндла контекста устройства (hDC - handleofDeviceContext) для окна, в которое будет осуществляться вывод изображения
2. Получения хэндла bitmap'а, который будет отображаться в окне
3. Получения совместимого с hDC контекста в памяти (для хранения изображения) с помощью функции CreateCompatibleDC
4. Выбора изображения (hBitmap) как текущего для контекста в памяти (hCompalibleDC)
5. Копирования изображения контекста в памяти (hCompatibleDC) на контекст устройства (hDC)
6. Удаления совместимого контекста (hCompatibleDC)