当前位置: 首页 > 文档资料 > DirectX 中文教程 >

DirectDraw对象

优质
小牛编辑
133浏览
2023-12-01

DirectDraw对象

返回上级


该节包含了关于DirectDraw对象的信息,以及如何通过IDirectDraw或IDirectDraw2接口对该对象进行操作。探讨了以下主题:

  1. 什么是DirectDraw对象?
  2. IDirectDraw2接口的新特性?
  3. 单进程的多DirectDraw对象
  4. 使用CoCreateInstance创建DirectDraw对象

什么是DirectDraw对象?

返回目录

DirectDraw对象是所有DirectDraw应用程序的核心,并且与Direct3D应用程序形成一个整体。它是你要创建的第一个对象,通过它,你可以创建所有其它相关的对象。典型的,通过调用DirectDrawCreate函数可以创建一个DirectDraw对象,它代表了IDirectDraw接口。如果你想使用该接口的另一个更高级的版本(比如:IDirectDraw2接口),以获得更加优秀的性能,你可以请求获得该接口。应注意的是,你可以创建若干个DirectDraw对象,每一个都代表了系统已安装的显示设备。

DirectDraw对象代表显示设备,并且可以利用硬件的加速特性。如果DirectDraw对象所实例化的显示设备具有硬件加速,则该对象是硬件加速的。DirectDraw对象可以创建三种对象:DirectDrawSurface(页面)、DirectDrawPalette(调色板)、和DirectDrawClipper(裁剪器)创建这些对象的函数分别是:IDirectDraw2::CreateSurface、IDirectDraw2::CreatePalette和IDirectDraw2::CreateClipper。

每次,多于一个的DirectDraw对象可以被实例化。最简单的例子是在Windows 95系统上使用两台显示器。尽管Windows 95并不支持双显示器,但为每一种显示驱动程序配置一个DirectDraw硬件抽象层(HAL)是可能的。当缺省的DirectDraw对象被实例化时,Windows 95和GDI将使用它所认识的显示驱动程序。Windows 95和GDI不认识的显示驱动程序可与另外一个设备相匹配,独立的DirectDraw对象必须通过第二个显示驱动程序的全局唯一标志符(GUID)来创建。这个GUID可由DirectDrawEnumerate函数获得。

DirectDraw对象管理它所创建的所有对象。它控制缺省的调色板(如果主页面是8位色彩模式)、缺省的关键色,和硬件显示模式。它跟踪哪些资源已经被分配了,以及哪些资源正有待分配。

IDirectDraw2接口的新特性?

返回目录

IDirectDraw2接口扩展了原先IDirectDraw接口的函数性:增加了一个IDirectDraw2::GetAvailableVidMem函数。该函数可以询问所有可用的视频RAM容量值,和当前可以为某种指定类型的页面所用的空余视频RAM容量值。

DirectX使用COM模型表明,可以通过提供新的接口而给旧的接口加入新的函数特性。在DirectX3的版本中,IDirectDraw2接口取代了原先的IDirectDraw接口。这个新的接口可以通过调用IDirectDraw::QueryInterface方法来获得,如下例所示:

……

//*********************************************************************

//本例程片段演示如何创建一个IDirectDraw2接口.

//*********************************************************************

LPDIRECTDRAW lpDD;

LPDIRECTDRAW2 lpDD2;

//首先创建一个IDirectDraw接口

ddrval = DirectDrawCreate(NULL, &lpDD, NULL);

if(ddrval != DD_OK)

return;

ddrval = lpDD->SetCooperativeLevel(hwnd, DDSCL_NORMAL);

if(ddrval != DD_OK)

return;

//获得新的接口

ddrval = lpDD->QueryInterface(IID_IDirectDraw2, (LPVOID *)&lpDD2);

if(ddrval != DD_OK)

return;

ddscaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;

ddrval = lpDD2->GetAvailableVidMem(&ddscaps, &total, &free);

if(ddrval != DD_OK)

return;


这个例子演示了用C++创建一个IDirectDraw接口的方法,然后再调用IDirectDraw::QueryInterface方法来创建一个IDirectDraw2接口。这个新接口包含了IDirectDraw2::GetAvailableVidMem函数,而试图从IDirectDraw接口调用该函数将会在编译的时候导致一个错误。

IDirectDraw2::GetAvailableVidMem是唯一一个被加入IDirectDraw接口的新方法。而且,IDirectDraw2::SetDisplayMode 和 IDirectDraw2::EnumDisplayModes,这两个方法被修改和扩展。

IDirectDraw::SetCooperativeLevel 和 IDirectDraw::SetDisplayMode之间的相互关系与 IDirectDraw2::SetCooperativeLevel 和 IDirectDraw2::SetDisplayMode之间的相互关系有一些改变。如果你使用旧的IDirectDraw接口,而且应用程序通过调用设置有DDSCL_EXCLUSIVE标志的IDirectDraw::SetCooperativeLevel取得了独占(全屏)显示模式,用IDirectDraw::SetDisplayMode来改变模式,再调用设置有DDSCL_NORMAL标志的IDirectDraw::SetCooperativeLevel来释放独占模式,原始的显示模式不会被还原。除非应用程序明确的调用IDirectDraw::RestoreDisplayMode方法或DirectDraw对象被销毁时,原始的显示模式才能恢复。然而,如果你使用新的IDirectDraw2接口,然后按着与上面同样的方法,当DirectDraw对象失去独占模式时,显示器的原始显示模式将会自动被恢复。

因为有些接口可能会因新接口的发布而该动,混合使用一个接口和它的替代者的方法(比如IDirectDraw 与IDirectDraw2)可以导致意想不到的错误。你必须只使用某接口的同一个版本的函数或方法。

单进程的多DirectDraw对象

返回目录

DirectDraw允许一个进程在需要的时候,可以任意多次的调用DirectDrawCreate函数。每次调用后,返回一个唯一的与设备无关的接口。每一个DirectDraw对象可以随心所欲的使用;在对象与对象之间没有相互依赖的关系。每个对象的行为就象它是由一个唯一的进程创建的。

因为DirectDraw对象之间是不相互依赖的,由一个特定的DirectDraw对象创建的DirectDrawSurface、DirectDrawPalette、和DirectDrawClipper对象不应该与其它的DirectDraw对象一起使用,因为这些对象会在它的DirectDraw对象销毁时而自动被释放。如果它们与其它的DirectDraw对象一起使用,调用它们的函数将在它们被销毁时退出。

例外的是,DirectDrawClipper对象是由DirectDrawCreateClipper函数创建的。这些对象与任何特定的DirectDraw对象是没有关系的,可以与一个或多个DirectDraw对象一起使用。

使用CoCreateInstance创建DirectDraw对象

返回目录

除了用常规的DirectDrawCreate方法创建一个DirectDraw对象外,你还可以使用CoCreateInstance函数,再调用IDirectDraw2::Initialize来创建一个DirectDraw对象。以下的例程片段描述了这个方法的各步骤。

第一步、在程序的最开始调用CoInitialize来初始化COM对象,参数为NULL。

if ( FAILED( CoInitialize( NULL )))

return FALSE;

第二步、然后,调用CoCreateInstance和IDirectDraw2::Initialize来创建DirectDraw对象。

ddrval = CoCreateInstance( &CLSID_DirectDraw,

NULL, CLSCTX_ALL, &IID_IDirectDraw2, &lpdd );

在CoCreateInstance函数中,第一个参数CLSID_DirectDraw,是DirectDraw驱动对象类的类标志符;IID_IDirectDraw2参数指定了要创建的特定的DirectDraw对象;最后的lpdd参数接收创建的对象。如果调用成功,这个函数返回一个没有初始化的对象。

第三步、在你使用这个DirectDraw对象之前,你必须调用IDirectDraw2::Initialize。在此之后,你就可以操作和释放该对象,就象它是用DirectDrawCreate创建的一样。如果在使用之前,你没有调用IDirectDraw2::Initialize,将返回DDERR_NOTINITIALIZED的错误。

if( !FAILED ( ddrval ))

ddrval = IDirectDraw2_Initialize( lpdd, NULL );

第四步、在关闭应用程序之前,使用CoUninitialize来关闭COM。

CoUnitialize();