Рейтинговые книги
Читем онлайн Графика для Windows средствами DirectDraw - Стэн Трухильо

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 32 33 34 35 36 37 38 39 40 ... 66

 }

 if (bmpdialog->DoModal()==IDCANCEL) {

  PostMessage(WM_CLOSE);

  return;

 }

 fullfilename=bmpdialog->fullfilename;

 filename=bmpdialog->filename;

 pathname=bmpdialog->pathname;

 int index=bmpdialog->GetIndex();

 DWORD w,h,d;

 if (bmpdialog->FilePalettized()) {

  w=palettemode[index].w;

  h=palettemode[index].h;

  d=palettemode[index].d;

 } else {

  w=nonpalettemode[index].w;

  h=nonpalettemode[index].h;

  d=nonpalettemode[index].d;

 }

 if (GetDisplayDepth()==8) primsurf->SetPalette(palette);

 ActivateDisplayMode(GetDisplayModeIndex(w, h, d));

 LoadBmp();

 ShowCursor(FALSE);

}

Функция ShowDialog() прежде всего проверяет, что текущий видеорежим имеет разрешение не менее 640×480. Из обсуждения функции SelectInitialDisplayMode() нам известно, что при инициализации приложения это условие заведомо выполняется, однако функция ShowDialog() также вызывается при каждом отображении BMP-файла. Если в данный момент установлен режим низкого разрешения, то перед тем, как продолжать, мы переходим в режим 640×480×8. Это обусловлено тем, что режимы низкого разрешения часто являются режимами Mode X, а GDI в таких режимах не может правильно отображать диалоговые окна.

Далее мы готовимся к отображению диалогового окна. Для палитровых режимов мы очищаем вторичный буфер и устанавливаем сохраненную ранее системную палитру, не пытаясь выводить диалоговое окно вместе с текущим изображением. Для беспалитровых режимов текущее изображение копируется на вторичный буфер и выводится за диалоговым окном.

СОВЕТ

Диалоговое окно и изображение

Чтобы организовать совместный вывод текущего изображения и диалогового окна в палитровом видеорежиме, вам придется сократить 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()

BOOL BmpViewWin::LoadBmp() {

 CWaitCursor cur;

 LPDIRECTDRAWSURFACE surf;

 surf=CreateSurface(filename, TRUE);

 if (surf) {

  if (bmpsurf)    bmpsurf->Release();

  bmpsurf=surf;

 } else {

  TRACE("failed to load new filen");

  return FALSE;

 }

 displayrect=GetDisplayRect();

 TRACE("display: %d %dn", displayrect.right, displayrect.bottom);

 GetSurfaceRect(bmpsurf, bmprect);

 TRACE("surface: %d %dn", bmprect.right, bmprect.bottom);

 int mx = displayrect.Width()-bmprect.Width();

 if (mx<0) {

  xscroll=TRUE;

  xlimit=mx;

  x=0;

 } else {

  xscroll=FALSE;

  x=mx/2;

 }

 int my = displayrect.Height()-bmprect.Height();

 if (my<0) {

  yscroll=TRUE;

  ylimit=my;

  y=0;

 } else {

  yscroll=FALSE;

  y=my/2;

 }

 update_screen=TRUE;

 return TRUE;

}

Сначала функция 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() выглядит так:

void BmpViewWin::DrawScene() {

 if (update_screen && bmpsurf) {

  ClearSurface(backsurf, 0);

  BltSurface(backsurf, bmpsurf, x, y);

  primsurf->Flip(0, DDFLIP_WAIT);

  update_screen=FALSE;

 }

}

Поскольку текущее положение поверхности рассчитывается в другом месте программы, а функция BltSurface() при необходимости автоматически выполняет отсечение, функция DrawScene() реализуется просто. Если переменная update_screen равна TRUE и существует поверхность для вывода, экран обновляется. Если поверхность не заполняет экран целиком, содержимое вторичного буфера стирается; если заполняет, то в стирании буфера нет необходимости. Затем функция BltSurface() копирует поверхность на вторичный буфер, а функция Flip() отображает изменения на экране. После того как обновление будет завершено, переменной update_screen присваивается значение FALSE

Обработка пользовательского ввода 

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

void BmpViewWin::OnKeyDown(UINT key, UINT nRepCnt, UINT nFlags) {

 switch (key) {

 case VK_UP:

  Up();

  break;

 case VK_DOWN:

  Down();

  break;

 case VK_LEFT:

  Left();

  break;

 case VK_RIGHT:

  Right();

  break;

 case VK_HOME:

  Home();

  break;

 case VK_END:

  End();

  break;

 case VK_PRIOR:

  PageUp();

  break;

 case VK_NEXT:

  PageDown();

  break;

 case VK_ESCAPE:

 case VK_SPACE:

 case VK_RETURN:

  ShowDialog();

  break;

 }

 DirectDrawWin::OnKeyDown(key, nRepCnt, nFlags);

}

С первого взгляда на листинг OnKeyDown() можно разве что понять, какие клавиши обрабатываются программой, потому что вся содержательная работа поручается другим функциям. Обратите внимание — при нажатии клавиш Escape, пробел и Enter вызывается одна и та же функция ShowDialog(). Это облегчает вызов диалогового окна после вывода изображения.

1 ... 32 33 34 35 36 37 38 39 40 ... 66
На этой странице вы можете бесплатно читать книгу Графика для Windows средствами DirectDraw - Стэн Трухильо бесплатно.
Похожие на Графика для Windows средствами DirectDraw - Стэн Трухильо книги

Оставить комментарий