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;
}
Сначала функция 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(). Это облегчает вызов диалогового окна после вывода изображения.
Остальные восемь функций, вызываемых функцией OnKeyDown(), изменяют положение поверхности во время прокрутки:
Читать дальше