Функция ShowDialog() вызывается при запуске приложения и при выборе нового файла. ShowDialog() подготавливает DirectDraw к отображению диалогового окна, выводит окно, получает информацию о выбранном BMP-файле и выбранном видеорежиме и отображает содержимое файла. Функция ShowDialog() приведена в листинге 5.7.
Листинг 5.7. Функция ShowDialog()
| void BmpViewWin::ShowDialog() { CRect displayrect=GetDisplayRect(); if (displayrect.Width()<640) ddraw2->SetDisplayMode( 640, 480, 8, 0, 0 );
if (GetDisplayDepth()==8) { ClearSurface( backsurf, 0 ); primsurf->SetPalette( syspal ); } else { BltSurface( backsurf, bmpsurf, x, y ); } ddraw2->FlipToGDISurface(); ShowCursor(TRUE); if (bmpdialog==0) { bmpdialog=new BmpDialog(); bmpdialog->SetArrays( &palettemode, &nonpalettemode ); } 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); } |
Далее мы готовимся к отображению диалогового окна.
Для палитровых режимов мы очищаем вторичный буфер и устанавливаем сохраненную ранее системную палитру, не пытаясь выводить диалоговое окно вместе с текущим изображением. Для беспалитровых режимов текущее изображение копируется на вторичный буфер и выводится за диалоговым окном.
СОВЕТ
Диалоговое окно и изображение
Чтобы организовать совместный вывод текущего изображения и диалогового окна в палитровом видеорежиме, вам придется сократить 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 file\n"); return FALSE; } displayrect=GetDisplayRect(); TRACE("display: %d %d\n", displayrect.right, displayrect.bottom); GetSurfaceRect( bmpsurf, bmprect ); TRACE("surface: %d %d\n", 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; } |