ddraw1->SetDisplayMode(640, 480, 8);
Выглядит довольно просто, поэтому давайте перейдем к версии SetDisplayMode()из интерфейса DirectDraw2. Ее традиционный прототип выглядит так:
HRESULT SetDisplayMode(DWORD width, DWORD height, DWORD depth, DWORD refreshrate, DWORD flags);
В этой версии появляются два дополнительных аргумента: частота смены кадров и двойное слово, которое может быть использовано в будущих версиях DirectDraw, а пока должно быть равно нулю. В расширенной версии SetDisplayMode()стандартный видеорежим VGA 640×480×8 можно активизировать так:
ddraw1->SetDisplayMode(640, 480, 8, 0, 0);
В данном случае вместо частоты смены кадров передается 0; это означает, что должна быть использована частота, принятая по умолчанию. Кроме того, можно указать конкретное значение частоты (60 Гц в следующем примере):
ddraw1->SetDisplayMode(640, 480, 8, 60, 0);
Однако не следует думать, что вы можете задать любую частоту (или другие параметры видеорежима). Перед тем как вызывать SetDisplayMode(), необходимо сначала определить параметры и частоты допустимых видеорежимов.
Обнаружение видеорежимов и частот смены кадров
В главе 3 говорилось о том, как функция EnumDisplayModes()интерфейса DirectDrawперечисляет все поддерживаемые видеорежимы. Через косвенно вызываемую функцию она сообщает вашему приложению о каждом видеорежиме, поддерживаемом установленными видеоустройствами. Прототип функции EnumDisplayModes()выглядит так:
HRESULT EnumDisplayModes(DWORD flags, LPDDSURFACEDESC desc, LPVOID callbackdata, LPDDENUMMODESCALLBACK callback);
Первый аргумент EnumDisplayModes()представляет собой набор флагов для описания дополнительных возможностей. Второй — является указателем на структуру DDSURFACEDESCс описанием необходимых атрибутов видеорежимов. Третий аргумент может использоваться для передачи данных косвенно вызываемой функции при каждом обращении к ней, а четвертый — является указателем на эту функцию. В главе 3 вызов EnumDisplayModes()выглядел так:
ddraw->EnumDisplayModes(0, 0, this, DisplayModeAvailable);
Первый и второй аргументы равны нулю; это означает, что мы не указываем флаги и критерии видеорежимов. Поскольку флаги (первый аргумент) не указаны, каждый обнаруженный видеорежим включается в список один и только один раз. Если бы в первом аргументе был указан флаг DDEDM_REFRESHRATES, каждый видеорежим вошел бы в список столько раз, сколько различных частот смены кадров в нем поддерживается. Такая возможность рассматривается ниже в этой главе при работе с частотами смены кадров в программе SuperSwitch.
Функция ActivateDisplayMode()
Как было сказано в начале главы, смена видеорежима не сводится к вызову функции SetDisplayMode(). Функция SetDisplayMode()активизирует нужный режим, но при этом необходимо уничтожить существующие поверхности и создать их заново. Класс DirectDrawWinрешает эту задачу за вас. В него входит функция ActivateDisplayMode(), выполняющая все действия, необходимые для активизации видеорежима и восстановления поверхностей приложения. Для удобства давайте снова посмотрим, как выглядит функция ActivateDisplayMode()(см. листинг 4.1).
Листинг 4.1. Функция DirectDrawWin::ActivateDisplayMode()
BOOL DirectDrawWin::ActivateDisplayMode(int mode) {
if (mode<0 || mode>=totaldisplaymodes) return FALSE;
DWORD width = displaymode[mode].width;
DWORD height = displaymode[mode].height;
DWORD depth = displaymode[mode].depth;
displayrect.left=0;
displayrect.top=0;
displayrect.right=width;
displayrect.bottom=height;
displaydepth=depth;
ddraw2->SetDisplayMode(width, height, depth, rate, 0);
curdisplaymode = mode;
TRACE("------------------- %dx%dx%d (%dhz) ---------------\n", width, height, depth, rate);
if (CreateFlippingSurfaces()==FALSE) {
FatalError("CreateFlippingSurfaces() failed");
return FALSE;
}
StorePixelFormatData();
if (CreateCustomSurfaces()==FALSE) {
FatalError("CreateCustomSurfaces() failed");
return FALSE;
}
return TRUE;
}
Функция ActivateDisplayMode()получает один аргумент — индекс в отсортированном списке обнаруженных видеорежимов. Сначала индекс проверяется на правильность. Если он соответствует допустимому элементу массива displaymode, высота, ширина и глубина заданного режима извлекаются из массива и используются для инициализации переменных displayrectи displaydepth. Затем атрибуты видеорежима используются при вызове функции SetDisplayMode(), активизирующей новый видеорежим.
Далее функция CreateFlipingSurfaces()создает первичную поверхность со вторичным буфером, а функция StorePixelFormatData()проверяет, не устарел ли формат пикселей DirectDrawWin(форматы пикселей подробно рассматриваются в главе 5). Наконец, мы вызываем функцию CreateCustomSurfaces(), отвечающую за создание вспомогательных поверхностей приложения.
Читать дальше