Графика для Windows средствами DirectDraw

Инициализация DirectDraw


Фактическое создание окна (вызов функции CreateEx()) заставляет Windows послать нашему приложению сообщение WM_CREATE. Класс DirectDrawWin перехватывает это сообщение в обработчике OnCreate(), созданном ClassWizard (см. листинг 3.1).

Листинг 3.1. Функция DirectDrawWin::OnCreate()


int DirectDrawWin::OnCreate(LPCREATESTRUCT) { pDirectDrawEnumerate(DriverAvailable, this); if (totaldrivers == 0) { AfxMessageBox("No DirectDraw drivers detected"); return -1; }

int driverindex=SelectDriver(); if (driverindex < 0) { TRACE("No DirectDraw driver selected\n"); return -1; } else if (driverindex > totaldrivers-1) { pAfxMessageBox("Invalid DirectDraw driver selected\n"); return -1; }

LPDIRECTDRAW ddraw1; DirectDrawCreate(driver[driverindex].guid, &ddraw1, 0); HRESULT r; r=ddraw1->QueryInterface(IID_IDirectDraw2, (void**)&ddraw2); if (r!=S_OK) { AfxMessageBox("DirectDraw2 interface not supported"); return -1; } ddraw1->Release(), ddraw1=0;

ddraw2->SetCooperativeLevel(GetSafeHwnd(), DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_ALLOWMODEX);

ddraw2->EnumDisplayModes(0, 0, this, DisplayModeAvailable); qsort(displaymode, totaldisplaymodes, sizeof(DisplayModeInfo), CompareModes); int initmode=SelectInitialDisplayMode(); if (ActivateDisplayMode(initmode) == FALSE) return -1;

return 0; }


Вся инициализация DirectDraw выполняется в функции OnCreate() (при поддержке нескольких вспомогательных функций). Процесс инициализации состоит из семи этапов:

  1. Получение списка всех драйверов DirectDraw.

  2. Выбор драйвера DirectDraw.

  3. Инициализация DirectDraw с использованием выбранного драйвера.



  4. Получение списка поддерживаемых видеорежимов.

  5. Выбор исходного видеорежима.

  6. Активизация выбранного видеорежима.

  7. Создание поверхностей приложения.

    Все эти этапы рассматриваются в последующих разделах.


    Третья задача, выполняемая функцией OnCreate(), — инициализация DirectDraw. Я снова привожу соответствующий фрагмент листинга 3.1:


    LPDIRECTDRAW ddraw1; DirectDrawCreate( driver[driverindex].guid, &ddraw1, 0 ); HRESULT r; r=ddraw1->QueryInterface( IID_IDirectDraw2, (void**)&ddraw2 ); if (r!=S_OK) { AfxMessageBox("DirectDraw2 interface not supported"); return -1; } ddraw1->Release(), ddraw1=0;

    ddraw2->SetCooperativeLevel( GetSafeHwnd(), DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX );


    Сначала мы объявляем ddraw1, указатель на интерфейс DirectDraw. Это локальный и, следовательно, временный указатель. Класс DirectDrawWin объявляет ddraw2, указатель на интерфейс DirectDraw2, однако мы не сможем инициализировать его без интерфейса DirectDraw. Функция DirectDrawCreate() инициализирует указатель ddraw1. Первый аргумент является указателем на GUID выбранного драйвера. Адрес указателя ddraw1 передается в качестве второго аргумента. Последний аргумент DirectDrawCreate() должен быть равен 0.

    Рис. 3.9. Диалоговое окно для выбора драйвера

    После того как интерфейс DirectDraw будет инициализирован, им можно воспользоваться для получения указателя на интерфейс DirectDraw2. Для этого следует вызвать функцию QueryInterface() и передать ей GUID интерфейса DirectDraw2, определенный под именем IID_IDirectDraw2. Если вызов QueryInterface() заканчивается неудачно, программа выводит диалоговое окно и завершает работу. Фактически мы требуем присутствия библиотеки DirectX версии 2 и выше (потому что интерфейс DirectDraw2 впервые появился в DirectX 2). Если вызов QueryInterface() окажется успешным, указатель ddraw1 освобождается. Попеременный вызов функций интерфейсов DirectDraw и DirectDraw2 не рекомендуется, поэтому освобождение указателя на интерфейс DirectDraw гарантирует, что в оставшейся части кода будет использоваться только интерфейс DirectDraw2.

    Затем мы вызываем функцию SetCooperativeLevel() и в качестве аргументов передаем ей логический номер нашего окна и три флага. По логическому номеру организуется взаимодействие окна с DirectDraw. При вызове SetCooperativeLevel() использованы три флага: DDSCL_EXCLUSIVE, DDSCL_FULLSCREEN и DDSCL_ALLOWMODEX. Флаги монопольного и полноэкранного режима обычно используются вместе для получения максимальных полномочий по управлению видеоустройством. Последний флаг означает, что все поддерживаемые видеорежимы Mode X должны быть доступны для выбора в программе. В Windows NT этот флаг игнорируется.



    Содержание раздела