分享
 
 
 

DirectDraw6的初级编程应用 —— 配合实例讲解,让你迅速入门

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

DirectDraw6的初级编程应用

by Gamster H. S

目录:

1.VC的环境设置.

2.浅谈COM.

3.DirectDraw简述.

4.DirectDraw的初级编程应用.

第一篇:VC的环境设置.

在进行任何DirectX有关的编程之前,你得先设置VC的环境变量值.主要是方便以后的项目设计.

我使用的是VC5和DirectX6,这是我的设置:

1.选择Options.

2.选择Directories Tab.

3.在Show directories for框中选择include files

4.在Directories框中选择一项新项,键入C:\mssdk\include,此目录将含有所有有关的头文件,

如:ddraw.h, dsound.h, ...

5.在Show directories for框中选择Library files

6.在Directories框中选择一项新项,键入C:\mssdk\lib,此目录将含有所有有关的库文件,

如:ddraw.lib, dsound.lib, dxguid.lib, ...

7.选择OK

当你编译建立微软的程式时,以下是基本步骤是:

1.将整个ddex1(c:\mssdk\multimedia\ddraw\ddraw\src\ddex1)目录copy到你任为合适的目

录中(如d:\mydd\,全称为d:\mydd\ddex1).

2.在VC5的菜单项Files中选择New.

3.选择Win32 Application.

4.键入合适的Location(如d:\mydd\).

5.键入合适的Project Name(在此为ddex1).

6.选择菜单项Project->Add to Project->Files,加入*.cpp文件,*.rc文件.在ddex1项目中,

你要加入ddex1.cpp和ddex1.rc文件.

7.选择菜单项Project->Settings,在Link中的Object/Library Modules中加入ddraw.lib

dxguid.lib.

8.Build and run.

9.Any prblems? You know where to find me!

第二篇:浅谈COM.

我不大清楚,但没几个人混得清楚的.他们要么知道点皮毛,要么还在OOP阶段锻练着.别人问

起,只说DirectX3,5,6运用许多COM技术.

第三篇:DirectDraw简述.

DirectX大大提高硬件在Win环境下的运用.DirectDraw提高各种显示硬件的工作.

第四篇:DirectDraw的初级编程应用.

本文将简述ddex1至ddex5中各种DirectDraw API的运用(in detail),至于更高的设计运用,望各位

自己慢慢从其他人手中学之.

1.DirectDraw例子中的全局变量.

file://-----------------------------------------------------------------------------

// Global data

file://-----------------------------------------------------------------------------

LPDIRECTDRAW4 g_pDD = NULL; // DirectDraw object

LPDIRECTDRAWSURFACE4 g_pDDSPrimary = NULL;// DirectDraw primary surface

LPDIRECTDRAWSURFACE4 g_pDDSBack = NULL; // DirectDraw back surface

LPDIRECTDRAWSURFACE4 g_pDDSOne = NULL; // Offscreen surface 1

LPDIRECTDRAWPALETTE g_pDDPal = NULL; // The primary surface palette

BOOL g_bActive = FALSE; // Is application active?

以上全局变量分别为:

1)IDirectDraw4的对象指针.用它建立其它几个全局变量.

2)IDirectDrawSurfce4的对象指针,在此是3个:

g_pDDSPrimary是显示缓冲块,用于显示;

g_pDDSBack是幕后显示缓冲块,从后屏缓冲区截图后拼在此缓冲块上,随后翻成显示缓冲

块,原有显示缓冲块翻成幕后显示缓冲块;

g_pDDSOne是后屏缓冲区,用于存储不同图形资料.

3)IDirectDrawPalette的对象指针,用于存储特定BITMAP的调色板.用在Color manipulation.

4)另一变量和DirectDraw无任何关系.只是确认程序是否处于运行状态.

以上的编码含有说明,所以对任何人都易理解.Any problems? You know where to find me!

2.初始化所有全程变量

这些原码我抄自ddex5.cpp中的static HRESULT InitApp(HINSTANCE hInstance, int nCmdShow)函数中:

1)定义几个局部变量:

DDSURFACEDESC2 ddsd; // the structure contain information about a particluar DirectDrawSurface.

DDSCAPS2 ddscaps; // this is important for further step

HRESULT hRet; // error output

LPDIRECTDRAW pDD; // IDirectDraw Object.

2)组建各项对象:

///////////////////////////////////////////////////////////////////////////

// Create the main DirectDraw object

///////////////////////////////////////////////////////////////////////////

hRet = DirectDrawCreate(NULL, &pDD, NULL);

if (hRet != DD_OK)

return InitFail(hWnd, hRet, "DirectDrawCreate FAILED");

先建立一个IDirectDraw Object,hRet装有DirectDrawCreate()的返回值,这一招非常有用,所有的DirectX

函数都返回一定的数值,DirectDraw的函数返回DD_OK表示函数调用成功.DDERR_***的返回值表示函数

调用失败(或其他原因).检查函数返回值,以备以后布骤不会出错.我将推迟解释InitFail()函数.

// Fetch DirectDraw4 interface

hRet = pDD->QueryInterface(IID_IDirectDraw4, (LPVOID *) & g_pDD);

if (hRet != DD_OK)

return InitFail(hWnd, hRet, "QueryInterface FAILED");

我们用COM中的QueryInterface申请一个IDirectDraw4对象,不同于DIRECTX5,DirectDraw增加了IDirectDraw4

界面,同时新增了几个更有用的函数(METHODS).你可以从DirectX的帮助文件中查到.虽是英文,

但好好啃一啃还是有收获的.

// Get exclusive mode

hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);

if (hRet != DD_OK)

return InitFail(hWnd, hRet, "SetCooperativeLevel FAILED");

我们接着设置显示方式,你可设置全屏,或视窗型,或MODEX,从DDEX1到DDEX5的程式中使用的显

示方式都是DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,全屏!你可以从DirectX的帮助文件中查到有关

SetCooperativeLevel()的注解.虽是英文,但好好啃一啃还是有收获的.

// Set the video mode to 640x480x8

hRet = g_pDD->SetDisplayMode(640, 480, 8, 0, 0);

if (hRet != DD_OK)

return InitFail(hWnd, hRet, "SetDisplayMode FAILED");

我们接着设置屏幕大小,色素和刷新速度.你可以从DirectX的帮助文件中查到有关SetDisplayMode()的

注解.虽是英文,但好好啃一啃还是有收获的.全屏下你所设显示可为320X200, 640X480, 800X600,

1024X768, 1280X1024, 1600X1280等等.色素从8, 16, 24, 32BITs.

// Create the primary surface with 1 back buffer

ZeroMemory(&ddsd, sizeof(ddsd));

ddsd.dwSize = sizeof(ddsd);

ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |

DDSCAPS_FLIP |

DDSCAPS_COMPLEX;

ddsd.dwBackBufferCount = 1;

hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);

if (hRet != DD_OK)

return InitFail(hWnd, hRet, "CreateSurface FAILED");

// Get a pointer to the back buffer

ddscaps.dwCaps = DDSCAPS_BACKBUFFER;

hRet = g_pDDSPrimary->GetAttachedSurface(&ddscaps, &g_pDDSBack);

if (hRet != DD_OK)

return InitFail(hWnd, hRet, "GetAttachedSurface FAILED");

建立一显示缓冲块附带一块幕后显示缓冲块.首先你初始化DDSURFACEDESC2的对象.如下:

ZeroMemory(&ddsd, sizeof(ddsd));

ddsd.dwSize = sizeof(ddsd);// you will fail without this!!

我观查到的现象是,每个DirectDraw结构含有dwSize成员,一定要初始化这个成员如下:

ddStructObj.dwSize = sizeof(DDSTRUCT);// you will fail without this!!

以下一段编码

ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |

DDSCAPS_FLIP |

DDSCAPS_COMPLEX;

表示所建DirectDrawSurface是Primary Surface(显示缓冲块),Flipable(前后翻转),有Back Buffer

(幕后显示缓冲块)连接到Primary Surface(attached to).

ddsd.dwBackBufferCount = 1;

表示Back Buffer(幕后显示缓冲块)只有一块.

hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);

if (hRet != DD_OK)

return InitFail(hWnd, hRet, "CreateSurface FAILED");

// Get a pointer to the back buffer

ddscaps.dwCaps = DDSCAPS_BACKBUFFER;

hRet = g_pDDSPrimary->GetAttachedSurface(&ddscaps, &g_pDDSBack);

if (hRet != DD_OK)

return InitFail(hWnd, hRet, "GetAttachedSurface FAILED");

这一段编码建立Primary Surface,再建立Back Buffer.至此我们的初始工程基本结束!

3.出错处理.

现在介绍初始化过程中错误的处理.

return InitFail(hWnd, hRet, "...... FAILED");

这一语段的运用是,当某一步初始化过程出错,整个程序退出,并显示一个对话框.其定义如下:

file://-----------------------------------------------------------------------------

// Name: InitFail()

// Desc: This function is called if an initialization function fails

file://-----------------------------------------------------------------------------

HRESULT InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...)

{

char szBuff[128];

va_list vl;

va_start(vl, szError);

vsprintf(szBuff, szError, vl);

ReleaseAllObjects();

MessageBox(hWnd, szBuff, TITLE, MB_OK);

DestroyWindow(hWnd);

va_end(vl);

return hRet;

}

你要增写一个RelaeseAllObject()函数,此函数将释放所有的DDRAW对象.有一点值得申明.如果对

象早已被释放,程序不知,试图释放不存在的对象将有严重后果,小心!!!!

file://-----------------------------------------------------------------------------

// Name: ReleaseAllObjects()

// Desc: Finished with all objects we use; release them

file://-----------------------------------------------------------------------------

static void ReleaseAllObjects(void)

{

if (g_pDD != NULL)

{

if (g_pDDSPrimary != NULL)

{

g_pDDSPrimary->Release();

g_pDDSPrimary = NULL;

}

if (g_pDDSOne != NULL)

{

g_pDDSOne->Release();

g_pDDSOne = NULL;

}

if (g_pDDPal != NULL)

{

g_pDDPal->Release();

g_pDDPal = NULL;

}

g_pDD->Release();

g_pDD = NULL;

}

}

这里,程序先释放IDirectDraw4下属的对象,再释放IDirectDraw4的对象.释放前,程序先确认各对

象是否存在,如对象还驻留于内村中,释放对象,并赋值对象指针NULL.

4.如何恢复暂时丢失的对象值.

在你按ALT+TAB键后,应用程序相互切换,当你从其他应用程序转换到DirectDraw有关应用程序时,原

有的对象缓冲区将在切换过程中被I/O系统释放.称为丢失(LOST).要重新建立.只有IDirectDraw4对

象属下的IDirectDrawSuface4对象有丢失的可能,所以IDirectDrawSurface4提供了Restore()程式.使用方式

如下:

file://-----------------------------------------------------------------------------

// Name: RestoreAll()

// Desc: Restore all lost objects

file://-----------------------------------------------------------------------------

HRESULT

RestoreAll(void)

{

HRESULT hRet;

hRet = g_pDDSPrimary->Restore();

if (hRet == DD_OK)

{

hRet = g_pDDSOne->Restore();

if (hRet == DD_OK)

{

//重新将Bitmap读入内存.DDReloadBitmap()

}

}

return hRet;

}

一般,DirectDrawSuface4对象的丢失将冲刷对象所含的Bitmap.故要使用DDReLoadBitmap()函数重新从

Bitmap文件中读入内存.此函数收藏於DDUTIL.CPP文件中.并不属于DirectX的一部分.下面,就让我

介绍如何使用DDUTIL.CPP中的函数.

5.使用DirectDraw Utilities!!

为了方便开发者,初学者对DirectX的困惑,MS DirectX设计组专门写了一个DDUTIL.CPP文件来帮助大

家.它提供了方便的函数来进行读取Bitmap并赋值于IDirectDrawSurface4对象,从Bitmap中读取调色板

信息,设置透明色等方程.定义如下:

/*==========================================================================

* File: ddutil.cpp

* Content: Routines for loading bitmap and palettes from resources

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

#ifdef __cplusplus

extern "C" { /* Assume C declarations for C++ */

#endif /* __cplusplus */

extern IDirectDrawPalette *DDLoadPalette(IDirectDraw4 *pdd, LPCSTR szBitmap);

extern IDirectDrawSurface4 *DDLoadBitmap(IDirectDraw4 *pdd, LPCSTR szBitmap, int dx, int dy);

extern HRESULT DDReLoadBitmap(IDirectDrawSurface4 *pdds, LPCSTR szBitmap);

extern HRESULT DDCopyBitmap(IDirectDrawSurface4 *pdds, HBITMAP hbm, int x, int y, int dx, int dy);

extern DWORD DDColorMatch(IDirectDrawSurface4 *pdds, COLORREF rgb);

extern HRESULT DDSetColorKey(IDirectDrawSurface4 *pdds, COLORREF rgb);

#ifdef __cplusplus

}

#endif /* __cplusplus */

-> DDLoadPalette(IDirectDraw4 *pdd, LPCSTR szBitmap):

从Bitmap文件中读出调色板信息,并将此信息交送于IDirectDraw4的对象.

1)参数IDirectDraw4 *是IDirectDraw4的对象指针.

2)参数LPCSTR,是Bitmap文件全名.

3)使用实例:

g_pDDPal = DDLoadPalette(g_pDD, "C:\\han\\mybitmap1.bmp");

if (g_pDDPal)

g_pDDSPrimary->SetPalette(g_pDDPal);

4)详情请参阅DDEX3-5.CPP

->DDLoadBitmap(IDirectDraw4 *pdd, LPCSTR szBitmap, int dx, int dy):

创建一块含有指定Bitmap的IDirectDrawSurface4对象,先创建一块足以容纳指定Bitmap的IDirectDrawSurface4

对象.再将Bitmap读入内存.

1)参数IDirectDraw4 *是对象指针.

2)参数LPCSTR,是Bitmap文件全名.

3)dx, dy表示Bitmap大小.

4)使用实例:

g_pDDSOne = DDLoadBitmap(g_pDD, "C:\\han\\mybitmap.bmp", 640, 490);

if(g_pDDSOne == NULL)

{

// Abort the program.

}

5)没有实例,多试试.

->DDReLoadBitmap(IDirectDrawSurface4 *pdds, LPCSTR szBitmap):

把一块Bitmap读入一个指定的IDirectDrawSurface4对象指针.

1)参数IDirectDrawSurface4 *是对象指针,将接收Bitmap.

2)参数LPCSTR,是Bitmap文件全名.

3)使用实例:

hRet = DDReLoadBitmap(g_pDDSOne, "C:\\han\\mybitmap.bmp");

if(FAILED(hret))

{

// Abort the program.

}

4)详情请参阅DDEX3-5.CPP

5)我用此函数最多.

->DDCopyBitmap(IDirectDrawSurface4 *pdds, HBITMAP hbm, int x, int y, int dx, int dy):

You don't need to know.

->DDColorMatch(IDirectDrawSurface4 *pdds, COLORREF rgb):

You don't need to know.

->DDSetColorKey(IDirectDrawSurface4 *pdds, COLORREF rgb):

在指定的参数IDirectDrawSurface4的对象指针上设置一transparent Colorkey.

1)参数IDirectDrawSurface4 *是对象指针,将接收ColorKey.

2)COLORREF, Colorkey的数值.

3)使用实例:

hRet = DDReLoadBitmap(g_pDDSOne, "C:\\han\\mybitmap.bmp");

if(FAILED(hret))

{

// Abort the program.

}

4)详情请参阅DDEX3-5.CPP

5)我用此函数也很多.

For more information about those functions, you better observe the examples Microsoft provided (DDEX1 - DDEX5) for

details.It is the easy way. All the implementations about those functions is in DDUTIL.CPP file.

6.BLIT, FLIP, &Color fill.

这三个应用是DirectDraw的主要应用.其功能为在BackBuffer上画上Bitmap图块,或填上一定的颜色,

再翻到屏幕上.所用函数为:

1>.Blt和BltFast在BackBuffer上画上Bitmap图块.

file://BltFast Example;

RECT rcRect;

rcRect.left = 0;

rcRect.top = 0;

rcRect.right = 640;

rcRect.bottom = 480;

while(1) {

ddrval = g_pDDSBack->BltFast(0, 0, g_pDDSOne, &rcRect, DDBLTFAST_WAIT);

if(ddrval == DD_OK)

{

break;

}

else if(ddrval == DDERR_SURFACELOST)

{

// use the restore all function!

RestoreAll();

}

}

我常用Blt function:

file://Blt Example;

RECT srcRect = {0, 0, 640, 480};

RECT dstRect = {0, 0, 640, 480};

DDBLTFX tempFX; // you will fail if you don't have this!

tempFX.dwsize = sizeof(DDBLTFX);// you will fail if you don't have this!

while(1) {

ddrval = g_pDDSBack->Blt(dstRect, g_pDDSOne, srcRect, DDBLT_WAIT, &tempFX);

if(ddrval == DD_OK)

{

break;

}

else if(ddrval == DDERR_SURFACELOST)

{

// use the restore all function!

RestoreAll();

}

else if(ddrval != DDERR_WASSTILLDRAWING)

{

break;

}

}

若想使用透明色(COLORKEY),改DDBLTFAST_WAIT(BltFast的最后一个参数)为

DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY.改DDBLT_WAIT(Blt的倒数第二个参数)为

DDBLT_WAIT | DDBLT_COLORSRC.

2.>用Blt在BackBuffer上填充颜色,(我从未成功过).

RECT dstRect = {0, 0, 640, 480};

DDBLTFX tempFX; // you will fail if you don't have this!

tempFX.dwsize = sizeof(DDBLTFX);// you will fail if you don't have this!

tempFX.dwFillColor = RGB(0, 255, 0); // green.

while(1) {

ddrval = g_pDDSBack->Blt(dstRect, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &tempFX);

if(ddrval == DD_OK)

{

break;

}

else if(ddrval == DDERR_SURFACELOST)

{

// use the restore all function!

RestoreAll();

}

else if(ddrval != DDERR_WASSTILLDRAWING)

{

break;

}

}

这个例码将在dstRect(0, 0, 640, 480)的长方形中填充绿色.长方形的大小和位置以你定义

的RECT对象确定.用Blt和BltFast的几个弱点是:

1)当dstRect(目标长方块)不和srcRect(源长方块)大小一致,Blt和BltFast将十分慢.

2)当dstRect部分超出屏幕,如屏幕大小640X480,你想在长方块{500, 500, 800, 600}中显示

图块,此图块不将处显,因为你定义的图块在屏幕以外!解决方法将在续篇(Advanced Section)中提出.

3.>使用Flip:

将准备好的BackBuffer翻到屏幕上,原来的Primar Surface变成BackBuffer.

while(1) {

ddrval = g_pDDSPrimary->Flip(NULL, DDFLIP_WAIT);

if(ddrval == DD_OK)

{

break;

}

else if(ddrval == DDERR_SURFACELOST)

{

// use the restore all function!

RestoreAll();

}

else if(ddrval != DDERR_WASSTILLDRAWING)

{

break;

}

}

4.总结:

1) 建立暂时的IDirectDraw对象.

2) 用COM中的QueryInterface来建立IDirectDraw4的对象.

3) SetCooperativeLevel (视窗或全屏).

4) SetDisplayMode(屏幕大小,色度,刷新速度).

5) 建立primary surface(屏幕显示内存),back buffer(幕后显示内存),和off-screen sufaces(备用显示内存,用于

存储图块).

6) 使用ddutil文件中的函数来读入Bitmap,设置ColorKey(当你进行Blt操作,这种颜色将不被显示).

7) 用Blt和BltFast将图块打入back buffer,用Flip来将准备好的back buffer翻成primary surface.原有的

primary surface翻成back buffer,等待下一轮Blt和BltFast的调用.

这些是DirectDraw版本6中的基本操作!我将写一个续篇(Advanced Section).Enjoy programming!

请大胆提出问题,写信给我或留言于留言板!感谢Doug Klopfenstein!他的Basic DirectDraw Programming

(谭翁编译了这一文章!)给我很大帮助.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有