Выбрать главу

 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 должен быть быстрым и универсальным. К счастью, дело обстоит именно так.