case 'S':
SaveSurface(primsurf, "SuperSwitch.bmp");
break;
default:
DirectDrawWin::OnKeyDown(nChar, nRepCnt, nFlags);
}
}
Все case-секции оператора switch были изменены для работы с новым меню. При нажатии клавиши Escape программа по-прежнему завершает работу, если меню частот в данный момент не отображается; тем не менее, если меню присутствует на экране, клавиша Escape просто скрывает его. Действие клавиш со стрелками также зависит от состояния меню. Если меню частот отображается, стрелки и изменяют выделенную частоту, а если нет — выделенный пункт в меню видеорежимов.
Самые существенные различия связаны с обработкой клавиши Enter. Если во время нажатия клавиши Enter меню частот не отображается, мы вызываем функции CreateRateMenuSurface() и UpdateRateMenuSurface() и присваиваем флагу ratemenu_up значение TRUE. Давайте рассмотрим эти две функции. Функция CreateRateMenuSurface() выглядит так:
BOOL SuperSwitchWin::CreateRateMenuSurface() {
if (ratemenusurf) ratemenusurf->Release(), ratemenusurf=0;
int rates=refresh_rates[selectmode].GetSize();
ratemenusurf=CreateSurface(80, rates*12+22);
return TRUE;
}
Сначала эта функция освобождает существующую поверхность (если таковая была создана ранее). Затем она определяет количество частот для выделенного в меню видеорежима и рассчитывает по ним размеры поверхности меню частот. Поверхность создается версией CreateSurface(), которой передаются ширина и высота новой поверхности.
Функция UpdateRateMenuSurface() отвечает за отображение текста меню. Выглядит она так:
BOOL SuperSwitchWin::UpdateRateMenuSurface() {
RECT rect;
GetSurfaceRect(ratemenusurf, rect);
rect.left++;
rect.top++;
rect.right--;
rect.bottom--;
if (!ClearSurface(ratemenusurf, 0, 200, 132)) TRACE("first Clear failed\n");
if (!ClearSurface(ratemenusurf, 0, 128, 100, &rect)) TRACE("second Clear failed\n");
HDC hdc;
ratemenusurf->GetDC(&hdc);
SelectObject(hdc, smallfont);
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, ratetextshadow);
ExtTextOut(hdc, 6, 4, 0, 0, rateheader, strlen(rateheader), 0);
SetTextColor(hdc, ratetextcolor);
ExtTextOut(hdc, 5, 3, 0, 0, rateheader, strlen(rateheader), 0);
CArray<DWORD,DWORD>& ratelist=refresh_rates[selectmode];
numrates=ratelist.GetSize();
for (int i=0; i<numrates; i++) {
char buf[10];
int len=sprintf(buf, "%d hz", ratelist[i]);
SetTextColor(hdc, ratetextshadow);
ExtTextOut(hdc, 11, i*12+18, 0, 0, buf, len, 0);
if (i==selectrate) SetTextColor(hdc, ratehighlightcolor);
else SetTextColor(hdc, ratetextcolor);
ExtTextOut(hdc, 10, i*12+17, 0, 0, buf, len, 0);
}
ratemenusurf->ReleaseDC(hdc);
return TRUE;
}
Прежде всего функция очищает поверхность, вызывая ClearSurface(). Затем содержимое массива refresh_rates используется для вывода текстовых строк, связанных с каждым пунктом меню. Вывод текста, как обычно, осуществляется функцией GetDC() интерфейса DirectDrawSurface в сочетании с текстовыми функциями Win32. Перед выходом из функции UpdateRateMenuSurface() контекст устройства, полученный функцией GetDC(), освобождается с помощью функции ReleaseDC().
ЗаключениеВ этой главе мы рассмотрели две демонстрационные программы и воспользовались такими возможностями DirectDraw, как переключение видеорежимов и частот смены кадров, а также применили цветовые ключи. Для переключения видеорежимов и частот использовалась функция EnumDisplayModes() интерфейса DirectDraw в сочетании с функцией SetDisplayMode(), а для работы с цветовыми ключами — функции SetColorKey() и BltFast() интерфейса DirectDrawSurface. Вывод текста в программах осуществлялся с помощью функции GetDC() интерфейса DirectDrawSurface и текстовых функций Win32.
В главе 5 мы научимся работать с поверхностями на уровне отдельных битов, что позволит установить максимальный контроль над содержимым палитровых и беспалитровых поверхностей. Затем полученные знания будут использованы для написания программы просмотра BMP-файлов.
Глава 5. Поверхности и форматы пикселей
Наверное, это самая важная глава во всей книге. Она посвящена поверхностям, а поверхности — главное, для чего создавалась библиотека DirectDraw. Поверхности DirectDraw позволяют хранить изображения, копировать и изменять их, переключать кадры и выводить графическую информацию на экран. Все интерфейсы DirectDraw в первую очередь ориентированы на работу с поверхностями. Интерфейс DirectDrawPalette облегчает интерпретацию палитровых поверхностей; интерфейс DirectDrawClipper определяет, какая часть (или части) поверхности будут копироваться при блиттинге; наконец, сам интерфейс DirectDraw обеспечивает основные средства для работы с поверхностями.
Поверхности
Поверхностью называется интерфейс, представляющий область памяти. Интерфейс DirectDrawSurface выполняет различные операции с этой памятью — размещение, копирование, переключение и освобождение. Интерфейс поверхностей позволяет написать практически любое графическое приложение.
Тем не менее следует заметить, что доступ к памяти поверхности должен предоставляться интерфейсом DirectDrawSurface; вы не сможете обратиться к поверхности никаким другим способом. Если учесть это обстоятельство, становится ясно, что интерфейс DirectDrawSurface должен быть быстрым и универсальным. К счастью, дело обстоит именно так.