📄 第7小节.txt
字号:
现在我们有了两个接口指针:一个是IDirectDraw接口,另一个是IDirectDraw7。后一个是我们想要的;前一个就没有用了。我们注意,在代码中每当找到一个新的有效对象时,前一个对象就通过Release()函数被释放掉。这个函数很简单:
ULONG Release(void);
返回的值是一个参考数字,只有在程序测试和调试时才用得着这个数字。为了安全起见,你还应该把释放了的指针赋值为NULL。我们也通常在声明这样的指针时设置它为NULL。你跟上我的节奏了吗?可能要记忆的东西太多了,但是你不得不记忆。让我们把谈到的这些做个实例吧,实例的目的是得到IDirectDraw7接口的指针:
LPDIRECTDRAW lpdd = NULL; // pointer to IDirectDraw (temporary)
LPDIRECTDRAW7 lpdd7 = NULL; // pointer to IDirectDraw7 (what we want)
// get the IDirectDraw interface pointer
if (FAILED(DirectDrawCreate(NULL, &lpdd, NULL)))
{
// error-handling code here
}
// query for IDirectDraw7 pointer
if (FAILED(lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7)))
{
// error-handling code here
}
else
{
// success! release IDirectDraw since we don't need it anymore
lpdd->Release();
lpdd = NULL;
}
现在,如果你是一个C程序员,你可能被调用QueryInterface()和Release()这两个函数的方法弄得有点模糊。你以前可能看过“->”这个符号,在C语言的结构部分,当结构声明了一个指针变量,调用结构成员时,就用“结构指针名->结构成员”,同样的道理,只是这里把结构成员换成了函数。既然说到这个话题,我就介绍一下另一个C++符号,范围定义符号“::”,它是表示从属关系的符号,举个例子你就明白了:比如QueryInterface()函数是属于IUnknown类的,就可以表示为IUnknown::QueryInterface()。我们将来会经常用到这个符号的,所以记住它。
说实在的,以上的主要目的是为了演示怎样使用QueryInterface()方法,它是所有DirectX接口的一部分,所以让我们往下进行。我们将直接使用COM方法获得接口指针。这种方法的好处是你可以立即获得IDirectDraw7接口指针,不用象刚才那么麻烦。首先,你必须得初始化COM,象这样:
HRESULT CoInitialize(LPVOID pvReserved);
不能在容易了,你必须把参数设置为NULL。当你结束COM调用,你需要抛弃它,也很简单:
void CoUninitialize(void);
我通常在DirecX程序的一开始就调用CoInitialize()函数,在程序的最末端,当我释放了所有的DirectX对象后,使用CoUninitialize()。一旦你初始化了COM,你就可以用CoCreateInterface()函数得到你想要的指针,它看起来有点丑陋:
STDAPI CoCreateInstance(
REFCLSID rclsid, // Class identifier (CLSID) of the object
LPUNKNOWN pUnkOuter, // Pointer to whether object is or isn't part
// of an aggregate
DWORD dwClsContext, // Context for running executable code
REFIID riid, // Reference to the identifier of the interface
LPVOID *ppv // Address of output variable that receives
); // the interface pointer requested in riid
如果成功,返回值是S_OK。参数需要好好解释一下,看下面:
※ REFCLSID rclsid:这是一个类标识符(不要同GUID搞混了哦),有为它准备好的常量标识符供你选择。对于IDirectDraw7来说,使用CLSID_DirectDraw。注意没有版本号,因为它是类标识符,不是接口标识符。
※ LPUNKNOWN pUnkOuter:这个同我们在DirectDrawCreate()中看到的一样,设置为NULL。
※ DWORD dwClsContext:这个必需的值叫作执行上下文,它定义了控制新生成对象的代码将要执行的方式。这个值可以从CLSCTX列表中选取,对于我们现在的情况,我们用CLSCTX_ALL,它包含了所有可能的值。
※ REIID riid:我们在QueryInterface()中看过它。这个IID是IID_DirectDraw7。
※ LPVOID *ppv:依然同DirectDrawCreate()中的一样,是指向接口指针的地址。
调用这个函数将取代我们上一个方法中的DirectDrawCreate()、QueryInterface()和Release()三个函数,所以简捷一些。当然,使用哪种随便你了。直接调用COM比我们先前用的方法少了一个多于地接口指针。一旦你用CoCreateInstance()建立了一个对象,你还得调用Initialize()函数初始化这个对象。在C++里可能写成这样IDirectDraw7::Initialize()。以下是它的原形:
HRESULT Initialize(GUID FAR *lpGUID);
将使用同DirectDrawCreate()中一样的GUID,就是NULL。在我们继续前,让我给你看一个使用COM创建DirectDraw对象的例子:
LPDIRECTDRAW7 lpdd7; // interface pointer
// initialize COM
CoInitialize(NULL);
// create the object
CoCreateInstance(CLSID_DirectDraw, NULL, CLSCTX_ALL, IID_IDirectDraw7, (void**)&lpdd7);
// initialize the object
lpdd7->Initialize(NULL);
直接看例子可能使你更容易理解一些。好了,建立DirectDraw对象的最难的两种方法你已经学会了,那就让我们看看最简单的方法吧!^_^ 它只有一步,没有多于的接口指针,不用设置COM,什么都没有。就是下面这个函数:
DirectDrawCreateEx(
GUID FAR *lpGuid,
LPVOID *lplpDD,
REFIID iid,
IUnknown FAR *pUnkOuter
);
所有的参数我们看起来都比较熟悉,因为我们刚才看过它们了。第一个,第二个和第四个参数同DirectDrawCreate()中的一样,只是这里需要用(void**)来修饰一下我们接口指针的地址——别问我为什么,这不是我的主意。第三个参数,riid,是我们在函数CoCreateInstance()中传递的接口ID,所以我们就用IID_IDirectDraw7。就这样,无论用哪种方法,我们得到了我们的DirectDraw对象,我们可以继续使用这个对象了。要做的头两件事是设置协作等级和显示协议。
☆ 设置协作等级和显示模式
待续。。。。。。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -