Графика для Windows средствами DirectDraw
Шрифт:
Функция ShowDialog
Далее мы готовимся к отображению диалогового окна. Для палитровых режимов мы очищаем вторичный буфер и устанавливаем сохраненную ранее системную палитру, не пытаясь выводить диалоговое окно вместе с текущим изображением. Для беспалитровых режимов текущее изображение копируется на вторичный буфер и выводится за диалоговым окном.
Диалоговое окно и изображение
Чтобы организовать совместный вывод текущего изображения и диалогового окна в палитровом видеорежиме, вам придется сократить 256 элементов палитры изображения до 236, добавить новые цвета в середину палитры (системные цвета занимают по 10 элементов в начале и в конце палитры) и пересчитать пиксели изображения в соответствии с внесенными изменениями. Обычно это ведет к снижению качества изображения, но присутствие диалогового окна все равно отвлекает внимание пользователя. Чтобы восстановить прежнее изображение, необходимо сохранить предыдущие варианты изображения и палитры.
Вызов функции FlipToGDISurface гарантирует, что вывод GDI будет присутствовать на экране. Кроме того, мы включаем курсор мыши (отключенный при запуске приложения классом DirectDrawWin), чтобы для работы с диалоговым окном можно было пользоваться мышью.
Далее мы создаем экземпляр класса BmpDialog, если он не был создан ранее. Класс-оболочка BmpDialog создается ClassWizard, он предназначен для отображения диалогового окна и работы с ним. Класс содержит код для работы с управляющими элементами окна и реакции на действия пользователя. Код класса BmpDialog здесь не рассматривается, так как он не имеет никакого отношения к DirectDraw.
Обратите внимание: при создании диалогового окна мы вызываем функцию SetArrays и передаем ей массивы palettemode и nonpalettemode в качестве аргументов. Эта функция передает диалоговому окну информацию о видеорежимах, предназначенных для отображения как палитровых, так и беспалитровых изображений.
Диалоговое окно отображается функцией DoModal. Пользователь сможет нажать кнопку Display лишь после того, как будет выбран BMP-файл и видеорежим. При этом мы сохраняем имя и путь выбранного BMP-файла и определяем параметры выбранного видеорежима. Если же пользователь закрывает диалоговое окно, мы посылаем сообщение WM_CLOSE и выходим из функции, завершая приложение.
Наконец, функция ActivateDisplayMode активизирует выбранный видеорежим, функция LoadBmp загружает содержимое BMP-файла, а курсор мыши отключается.
Чтобы лучше понять, как происходит загрузка файла, необходимо рассмотреть функцию LoadBmp, которая не только загружает BMP-файл, но и инициализирует
механизм прокрутки. Функция LoadBmp приведена в листинге 5.8.Листинг 5.8. Функция LoadBmp
Сначала функция LoadBmp создает объект MFC CWaitCursor, чтобы на время ее работы на экране отображался курсор Windows в виде песочных часов. Затем она вызывает функцию CreateSurface и передает ей в качестве аргумента имя выбранного BMP-файла. Реализация CreateSurface рассматривалась ранее в этой главе, поэтому мы знаем, что эта функция загружает указанный BMP-файл на новую поверхность.
Затем LoadBmp определяет параметры новой поверхности и текущий активный видеорежим и использует полученные данные для инициализации переменных класса BmpViewWin, связанных с прокруткой и позиционированием поверхностей. Если размеры поверхности меньше размеров видеорежима, поверхность центрируется на экране; если поверхность больше, следует разрешить ее прокрутку. Переменные x и y определяют текущую позицию на поверхности, а переменные xlimit и ylimit ограничивают диапазон прокрутки. Логические переменные xscroll и yscroll показывают, разрешена ли горизонтальная и вертикальная прокрутка поверхности.
Наконец, логической переменной update_screen присваивается значение TRUE; оно говорит о том, что функция DrawScene должна обновить первичную поверхность. О функции DrawScene речь пойдет в следующем разделе.
Функция DrawScene обновляет экран в зависимости от состояния логической переменной update_screen. Если переменная update_screen равна FALSE, предполагается, что содержимое первичной поверхности не устарело, и делать ничего не нужно. Функция DrawScene выглядит так: