📄 第8小节.txt
字号:
typedef struct _DDSCAPS2{
DWORD dwCaps;
DWORD dwCaps2;
DWORD dwCaps3;
DWORD dwCaps4;
} DDSCAPS2, FAR* LPDDSCAPS2;
最重要的就是dwCaps了。第三个和第四个成员从来没有用过,是为将来准备的。总之,dwCaps可以使用如下的值,当然可以用“|”组合。以下是最为常用的,其它的你若有兴趣,自己查好了^_^
※ DDSCAPS_BACKBUFFER:指出这个表面是需要表面切换结构的后缓冲区。
※ DDSCAPS_COMPLEX:是一个复杂表面,由主表面,一个或多个粘贴表面组成,通常是为了页面切换。
※ DDSCAPS_FLIP:指出这个表面是表面切换结构的一部分。前缓冲区紧跟着一个或多个建立好的后缓冲区。
※ DDSCAPS_FRONTBUFFER:是关于表面切换结构的前缓冲区。
※ DDSCAPS_LOCALVIDMEM:指出在true、local video memory【不知怎么翻译】中建立表面。如果使用该标志,必须也同时使用DDSCAPS_VIDEOMEMORY标志,但不能同DDSCAPS_NONLOCALVIDMEM标志同时使用。
※ DDSCAPS_MODEX:指出这个表面是Mode X模式(320×200或320×240)的表面。
※ DDSCAPS_NONLOCALVIDMEM:指出表面建立在non-local video memory【不知怎么翻译】中。如果定义该标志,必须也同时使用DDSCAPS_VIDEOMEMORY标志。但是不能同DDSCAPS_LOCALVIDMEM同时使用。
※ DSCAPS_OFFSCREENPLAIN:这是一个简单的离屏表面。
※ DDSCAPS_OWNDC:这个表面将具有长周期的设备上下文。
※ DDSCAPS_PRIMARYSURFACE:主表面。
※ DDSCAPS_STANDARDVGAMODE:是标准的VGA模式表面。不能同DDSCAPS_MODEX同用。
※ DDSCAPS_SYSTEMMEMORY:建立在系统内存里的表面。
※ DDSCAPS_VIDEOMEMORY:这个表面建立在显示内存里。
天啊,终于介绍完了这个结构。现在我们准备建立表面吧。第一步当然是填充DDSURFACEDESC2结构。Microsoft推荐大家当你使用一个结构之前,你应该把它先初始化为0。有鉴于此,我经常使用这样一个宏:
#define INIT_DXSTRUCT(dxs) { ZeroMemory(&dxs, sizeof(dxs)); dds.dwSize = sizeof(dxs); }
它可以用于任何一个DirectX结构,因为它们都有dwSize成员,所以这是很方便的。如果你以前从来没有看过ZeroMemory()这个函数,它只是由函数memset()扩充来的宏,在Windows的头文件中用#define定义好了,所以你不需要用#indlude添加任何东西就可以用它。
初始化了结构之后,你得根据实际情况设置表面了。对于主表面,你需要ddsCaps和dwBackBufferCount,对于离屏缓冲区,你也需要dwHeight和dwWidth,但不需要dwBackBufferCount。对于一些表面你可能还需要颜色值,但我们不把它弄得太复杂了。填充完结构后,你需要调用IDirectDraw7::CreateSurface()函数,原形是这样:
HRESULT CreateSurface(
LPDDSURFACEDESC2 lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE7 FAR *lplpDDSurface,
IUnknown FAR *pUnkOuter
);
这些参数的意义可能你也能猜出个大概了,毕竟我们已经习惯了这些疯狂的DirectX素材:
※ LPDDSURFACEDESC2 lpDDSurfaceDesc:表示要创建表面的描述结构。当然是个指针了。
※ LPDIRECTDRAWSURFACE7 FAR *lplpDDSurface:为指向表面指针的指针。此参数在此函数调用成功后填充。为什么要使用指向指针的指针呢?这是因为我们的任务就是分配一片表面内存区域,这样只能使用指针(表面指针)作为操作该表面内存区域的标志,返回值应该是该指针值而不是该指针所表示的内容(具体的表面)。当我们使用函数参数传递该值时,又只能使用指针(即指针的指针)修改表面指针的内容而不是表面指针所代表的表面内存区域。(理论复杂,使用简单,不明白不要太在意)
※ IUnknown FAR *pUnkOuter:看过这个模式吧,无论何时调用pUnkOuter,都是关于COM应用的,我们不想在这儿浪费时间,设置为NULL好了。
来个实例吧,你会明白一切的。希望在实例里,我们要一个主表面和一个紧随主表面的后缓冲区,还有一个离屏缓冲区用来放置位图。假设我们已经得到了IDirectDraw7接口指针,代码如下:
DDSURFACEDESC2 ddsd; // surface description structure
LPDIRECTDRAWSURFACE7 lpddsPrimary = NULL; // primary surface
// set up primary drawing surface
INIT_DXSTRUCT(ddsd); // initialize ddsd
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // valid flags
ddsd.dwBackBufferCount = 1; // one back buffer
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | // primary surface
DDSCAPS_COMPLEX | // back buffer is chained
DDSCAPS_FLIP | // allow page flipping
DDSCAPS_VIDEOMEMORY; // create in video memory
// create primary surface
if (FAILED(lpdd7->CreateSurface(&ddsd, &lpddsPrimary, NULL)))
{
// error-handling code here
}
你当然还可以用CreateSurface()函数创建复杂表面,只是使用DDSCAPS_COMPLEX标志罢了。由于刚才我们创建了一个后缓冲区,所以我们还得必须得到指向它的指针。那就得调用IDirectDrawSurface7::GetAttachedSurface()函数了:
HRESULT GetAttachedSurface(
LPDDSCAPS2 lpDDSCaps,
LPDIRECTDRAWSURFACE7 FAR *lplpDDAttachedSurface
);
参数很简单啦:
※ LPDDSCAPS2 lpDDSCaps:指向创建后缓冲区表面的DDSCAPS2结构。你就可以使用DDSCAPS2结构中相应的成员了。
※ LPDIRECTDRAWSURFACE7 FAR *lplpDDAttachedSurface:后缓冲区表面指针的地址。简单理解为声明一个指针,然后把指针的地址传递给该参数。
看看下面的代码就明白了:
LPDIRECTDRAWSURFACE7 lpddsBack = NULL; // back buffer
// get the attached surface
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
if (FAILED(lpddsPrimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsBack)))
{
// error-handling code here
}
感觉有点儿入门了吗?如果你很难记住以上步骤,那么你是一个正常人,反复运用就会熟悉了。没有人能记住所有的庞大的结构成员和标志常量,这就是我们手边总是准备程序员参考手册或者拥有MSDN Library CD的原因了^_^ !OK,最后一步是建立离屏缓冲区。假设它的宽400,高300,(单位是象素)代码如下:
LPDIRECTDRAWSURFACE7 lpddsOffscreen = NULL; // offscreen buffer
// set up offscreen surface
INIT_DXSTRUCT(ddsd); // initialize ddsd
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; // valid flags
ddsd.dwWidth = 400; // set width
ddsd.dwHeight = 300; // set height
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | // offscreen buffer
DDSCAPS_VIDEOMEMORY; // video memory
// create offscreen buffer
if (FAILED(lpdd7->CreateSurface(&ddsd, &lpddsOffscreen, NULL)))
{
// error-handling code here
}
表面这些学问就介绍到这儿,还有好多东西要介绍,可是唯一的问题是文章太长了,我们先暂停吧。你现在可以建立一个最基本的,但是什么也不显示的表面。
千万记住了,你使用的每一个DirectDraw接口和所有的表面,用完后一定要释放(Release)它们啊!切记、切记!!!!!!!
☆ 总结
很抱歉在这里中断了,尤其是你还没有看到显示的图形,但关于图形有太多的内容了,不是三言两语就能说清除的,所以放到下两章。下一章讨论DirectDraw中的调色板和象素,再下下一章讨论DirectDraw中的位图。精彩在后面哦!请耐心期待。
待续。。。。。。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -