DirectX基础与恐怖的COM

创建和使用DirectX接口
此刻,我想你以及东大COM是接口的集合。而接口是简单的函数指针(确切地说是VTABLE)。从而,应用一个DirectX COM对象时,你所要做的一切便是创建它,获取一个接口指针,然后用适当的语法对接口调用函数。譬如,我用主DirectDraw接口来演示一下:
首先,你需要三样东西来用DirectDraw做试验。
·DirectDraw运行时COM对象和DDL必须被加载和注册。这是DirectX安装程序干的事情。
·你必须在你的win32程序中include DDRAW.LIB输入库,以便可以链接到你调用的函数。
·你必须在你的程序中include DDRAW.H,这样编译器才能够识别到DirectDraw的头文件信息、原型声明很数据类型。
知道这些之后,下面是DirectDraw1.0接口指针的数据类型:
LPDIRECTDRAW lpdd = NULL;
以及DirectDraw4.0接口指针的数据类型:
LPDIRECTDRAW7 lpdd = NULL;
以及DirectDraw7.0的:
LPDIRECTDRAW7 lpdd = NULL;
不过没有8.0的了。

现在,创建创建DirectDraw COM对象并获得DirectDraw对象的接口指针(DirectDraw对象代表显卡),你所要做的一切便是想下面这般使用打包了的函数DirectDrawCreate():
DirectDrawCreate(NULL, &lpdd, NULL);
这将返回基本的DirectDraw1.0接口。在第六章“初次接触:DirectDraw”我将讨论有关参量的细节。但现在,只要知道,这个调用创建一个DirectDraw对象,并把接口指针赋给lpdd。

现在,你已经准备好针对DirectDraw做些调用了。暂且留步!你并不知道可以用那些函数或方法,呵呵,这正是你读本书的目的。作为例子,下面的代码表明你你如何设置一个640×480,256色深的视频模式:

lpdd->SetVideoMode(640, 480, 256);

除了简单你还能说什么呢?唯一额外的工作便是便是哪个对从DirectDraw接口指针lpdd进行的“->”操作。当然,真正发生的事情是检索接口的虚函数表,但在这里并看不出这个。

本质上说,任何对DirectX的调用均是下面的形式:

interface_pointer->method_name(parameter list);

当然,垠xEbAz专i35$QuEbLl通过使用QueryInterface(),你可以从最初的DirectDraw接口跳转到任何你想使用的接口上(比如DirectX3D)。甚至,有多个DirectX版本,不久前,Microsoft停止了编写获得任何最新界面的打包函数。所以,有时,你不得不自己使用QueryInterface()手动获得最新版本的DirectX接口。让我们对此研究研究。

接口的查询
DirectX的一个诡异的地方是所有的版本号均不同步。这还真是个问题,而且绝对是个导致困惑的源头。下面是事情的缘由:当第一个DirectX版本发布是,DirectDraw的接口被命名为:
IDIRECTDRAW
然后,当DirectX2.0发布时,DirectDraw被更新到2.0。于是我们便有了:
IDIRECTDRAW
IDIRECTDRAW2
现在,当DirectX6.0发布时,我们看到的是:
IDIRECTDRAW
IDIRECTDRAW2
IDIRECTDRAW4
IDIRECTDRAW7
而到了DirectX8.0,便不在支持DirectDraw了。所以你所有的最新版的DirectDraw接口便只是IDIRECTDRAW7了。明白了吗?

等一下!咋没接口3和接口5?我也不知道,但是这确实是个问题。但关键是,就算你使用DirectX8.0,这并不意味着接口也被更新到8.0。进一步说,DirectX版本号和各接口的版本号已经各个接口版本号之间可以完全的不同步。DirectX6.0的DirectDraw接口版本到IDIRECTDRAW4,但是DirectSound接口只到1.0,那时叫IDIRECTSOUND。瞧这个乱啊。上述叙述是想告诉你,当你使用一个DirectX接口是你应当确保你使用的接口是最新版的。如果你不肯定,那使用1.0版接口的指针,通过通用创建函数以得到最新的接口版本。

为了解释一下刚才我到底在说些什么,下面是个例子:DirectDrawCreate()返回一个1.0版的接口指针,但是DirectDraw已经到了IDIRECTDRAW7了,那么你如何才能利用到新功能呢?
有两种方法:使用低级COM函数,或使用QueryInterfaced()。让我们使用后者吧。整个过程大致如下:首先,你DirectDrawCreate()以创建DirectDraw COM接口,其返回讨厌的IDIRECTDRAW接口指针。然后,你使用这个指针来调用QueryInterface(),并通过接口ID(或GUID)获取IDIRECTDRAW7指针。下面是个例子:
LPDIRECTDRAW  lpdd;   // version 1.0
LPDIRECTDRAW7 lpdd7;  // version 7.0

// create version 1.0 DirectDraw object interface
DirectDrawCreate(NULL, &lpdd, NULL);

// now look in DDRAW.H header, find IDIRECTDRAW7 interface
// ID and use it to query for the interface
lpdd->QueryInterface(IID_IDirectDraw7, &lpdd7);

此刻,你有两个接口指针。但你不需要指向IDIRECTDRAW的指针。所以你应该释放该指针。
// release, decrement reference count
lpdd->Release();

// set to NULL to be safe
lpdd = NULL;

记住了吗?当你用完了之后你应当释放接口。因而,但你的程序结束时你同样应当释放IDIRECTDRAW7接口,如下:
// release, decrement reference count
lpdd7->Release();

// set to NULL to be safe
lpdd7 = NULL;

Ok,现在你知道如何从一个接口得到另一个接口指针了吧。够烦琐的吧,在DirectX7.0我们见到了一缕希望。Microsoft添加了一个新函数DirectDrawCreateEx(),其直接返回IDIRECTDRAW7接口。神奇吧?但他们又在DirectX8.0中枪毙了该函数。但谁在乎呢?反正我们仍然可以使用这个函数:
HRESULT WINAPI DirectDrawCreateEx(
  GUID FAR *lpGUID,  // the GUID of the driver, NULL for active display
  LPVOID *lplpDD,    // receiver of the interface
  REFIID iid,       // the interface ID of the interface you are requesting
  IUnknown FAR *pUnkOuter  // advanced COM, NULL
);
这个新函数允许你发生一个iid表明想要请求的DirectDraw版本,然后函数将为你创建一个COM对象。我们只需这样调用函数:

LPDIRECTDRAW7 lpdd;  // version 7.0

// create version 7.0 DirectDraw object interface
DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL);

基本上,对DirectDrawCreateEx的调用直接创建一个所要求的接口。所以你无须用DirectDraw1.0做为中介了。好了,这便是所有有关使用DirectX和COM的知识。当然,你还没有看到DirectX组件拥有的数百个函数和接口。不过后面你将看到的。

COM的未来
目前,已经发布了许多类似COM的技术,比如CORBA(Common Object Request Broker Architecture)。但是,由于你只关心Windows游戏,其他技术便显得不是很重要了。
最新版本的COM是COM++,其更强大,规则更合理,以及深思熟虑的实现细节。COM++使分布式软件组件开发更加容易。诚然,COM++比COM要复杂一点,不过嘿嘿,这就是生活。
除了COM和COM++还有一个完全Internet/intranet版本的COM叫做DCOM(分布式COM)。拜DCOM所赐,COM对象甚至无须在你的机器上。他们可以有网络上的其他机器提供。酷不酷?试想一下,你的程序作为一个强大DCOM服务器下的一个客户端。照我看,真是个难以置信的技术。

摘要
本章覆盖了一些有趣的技术资料和概念。COM不容易理解,所以要想理解它还真的刻苦学习一下。但是,使用COM就太简单了,这一点你将在下一章看到。总之,你浏览了一下DirectX和它所有的组件。所以,在下面的章节中,一旦你知道了每个组件的细节,并且知道如何使用它们,你便会对它们如何协调在一起有个更好的认识了。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值