Функция GetGUID()
Функция GetGUID() применяется для получения GUID (глобального уникального идентификатора) идентифицирующего создаваемое функцией CreateDeviceFromClipper() устройство. Если вместо вызова функции GetGUID() использовать значение NULL, функция CreateDeviceFromClipper() автоматически выберет устройство с цветовой моделью Ramp. Мы вызываем функцию GetGUID() чтобы иметь возможность выбрать цветовую модель Ramp или RGB. Текст функции GetGUID() приведен в листинге 4.2.
Листинг 4.2. Функция GetGUID()
| |
GUID* RMWin::GetGUID() { static GUID* lpguid; HRESULT r;
D3DFINDDEVICESEARCH searchdata; memset(&searchdata, 0, sizeof searchdata); searchdata.dwSize = sizeof searchdata; searchdata.dwFlags = D3DFDS_COLORMODEL; searchdata.dcmColorModel = colormodel;
static D3DFINDDEVICERESULT resultdata; memset(&resultdata, 0, sizeof resultdata); resultdata.dwSize = sizeof resultdata;
LPDIRECTDRAW ddraw; r = DirectDrawCreate(NULL, &ddraw, NULL); if (r != DD_OK) { TRACE("DirectDrawCreate failed\n"); return NULL; }
LPDIRECT3D d3d; r = ddraw->QueryInterface(IID_IDirect3D, (void**)&d3d); if (r != D3DRM_OK) { TRACE("d3drm->QueryInterface failed\n"); ddraw->Release(); return NULL; }
r = d3d->FindDevice(&searchdata, &resultdata); if (r == D3D_OK) lpguid = &resultdata.guid; else { TRACE("FindDevice failure\n"); lpguid = NULL; }
d3d->Release(); ddraw->Release();
return lpguid; }
| |
Перед тем, как продолжить, посмотрим, почему функция GetGUID() такая сложная. Наша задача — получить GUID для заданного устройства Direct3D. Казалось бы, интерфейс Direct3DRM должен предоставлять функцию, выполняющую эту работу. Возможно, библиотека Direct3D и могла бы быть разработана таким способом, но этого не произошло.
Мы применяем абстрактный режим Direct3D, а абстрактный режим в свою очередь зависит от непосредственного режима, который фактически выполняет визуализацию. Это означает, что устройство Direct3D является конструкцией непосредственного режима, и для поиска требуемого устройства необходимо воспользоваься интерфейсом непосредственного режима.
Функции непосредственного режима доступны через COM-интерфейс Direct3D.
Мы можем получить указатель на интерфейс Direct3D создав интерфейс DirectDraw и вызвав его функцию QueryInterface(). Это возможно, поскольку объект DirectDraw начиная с DirectX версии 2 поддерживает интерфейс Direct3D. Если бы мы работали с DirectX версии 1, такой вызов QueryInterface() закончился бы неудачей.
Давайте взглянем на начало функции GetGUID() (листинг 4.2). Первое, что делает функция, — это подготовка двух структур, применяемых для хранения информации об устройстве. Структура searchdata используется для указания запрашиваемой цветовой модели, а в структуре resultdata хранятся результаты поиска. Ниже приведен фрагмент программы, создающий и инициализирующий эти структуры:
D3DFINDDEVICESEARCH searchdata; memset(&searchdata, 0, sizeof searchdata); searchdata.dwSize = sizeof searchdata; searchdata.dwFlags = D3DFDS_COLORMODEL; searchdata.dcmColorModel = colormodel;
static D3DFINDDEVICERESULT resultdata; memset(&resultdata, 0, sizeof resultdata); resultdata.dwSize = sizeof resultdata;
Функция memset() обнуляет все поля, после чего полю dwSize присваивается размер структуры.
СОВЕТ |
|
Поле dwSize. Требование, чтобы поле структуры содержало размер самой структуры, может показаться довольно глупым, но это сделано, чтобы позволить расширение функциональности без модификации старых программ. Microsoft может увеличить размер структуры в будущей версии Direct3D, а программы, написанные сегодня, будут работать, потому что Direct3D сможет определить, основываясь на значении поля dwSize, какая версия структуры используется. |
Полю dwFlags присваивается значение константы D3DFDS_COLORMODEL — это указывает, что единственным критерием поиска является заданная цветовая модель устройства. Полю dcmColorModel присваивается значение переменной colormodel. По умолчанию значение переменной colormodel равно D3DCOLOR_MONO, но оно может быть изменено функцией SetColorModel() (см.
выше функцию InitInstance()).
На следующем этапе работы функции GetGUID() создается интерфейс DirectDraw:
LPDIRECTDRAW ddraw; r = DirectDrawCreate(NULL, &ddraw, NULL); if (r != DD_OK) { TRACE("DirectDrawCreate failed\n"); return NULL; }
Функция DirectDrawCreate() применяется для получения указателя на интерфейс DirectDraw. Если вызов функции завершается неудачно, макроопределение TRACE отображает соответствующее сообщение, после чего возвращается NULL.
Как только указатель на интерфейс DirectDraw получен, у объекта запрашивается интерфейс Direct3D:
LPDIRECT3D d3d; r = ddraw->QueryInterface(IID_IDirect3D, (void**)&d3d); if (r != D3DRM_OK) { TRACE("d3drm->QueryInterface failed\n"); ddraw->Release(); return NULL; }
Константа IID_IDirect3D представляет собой GUID интерфейса Direct3D и применяется здесь, чтобы указать функции QueryInterface() какой интерфейс мы ищем. Если функция завершается нормально, переменная d3d указывает на экземпляр интерфейса Direct3D. При возникновении ошибки выводится отладочное сообщение и функция возвращает NULL предварительно освободив интерфейс DirectDraw.
Теперь мы можем выполнить поиск GUID устройства:
r = d3d->FindDevice(&searchdata, &resultdata); if (r == D3D_OK) lpguid = &resultdata.guid; else { TRACE("FindDevice failure\n"); lpguid = NULL; }
Функция FindDevice() интерфейса Direct3D получает в качестве аргументов указатели на две подготовленные ранее структуры. Если функция возвращает D3D_OK, значит GUID найден и переменной lpguid присваивается указатель на него.
Обратите внимание, что структура resultdata и переменная lpguid объявлены как статические. Это сделано потому, что GUID представляет собой 128-разрядное значение. Объявив эти переменные статическими, мы можем возвратить указатель на GUID, а не делать копию его значения.
Перед завершением работы функция GetGUID() освобождает интерфейсы DirectDraw и Direct3D.
Содержание раздела