登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
  立华软件园 - 安全技术中心 - 技术文档 - 入门基础 技术文章 | 相关下载 | 电子图书 | 攻防录像 | 安全网站 | 在线论坛 | QQ群组 | 搜索   
 安全技术技术文档
  · 安全配制
  · 工具介绍
  · 黑客教学
  · 防火墙
  · 漏洞分析
  · 破解专题
  · 黑客编程
  · 入侵检测
 安全技术工具下载
  · 扫描工具
  · 攻击程序
  · 后门木马
  · 拒绝服务
  · 口令破解
  · 代理程序
  · 防火墙
  · 加密解密
  · 入侵检测
  · 攻防演示
 安全技术论坛
  · 安全配制
  · 工具介绍
  · 防火墙
  · 黑客入侵
  · 漏洞检测
  · 破解方法
 其他安全技术资源
  · 攻防演示动画
  · 电子图书
  · QQ群组讨论区
  · 其他网站资源
最新招聘信息

游戏编程起源(初学者)Ⅷ
发表日期:2007-01-17作者:[转贴] 出处:  

☆ 设置协作等级和显示模式
我不需要说太多。Windows编程设置协作级别你只需要调用IDirectDraw7::SetCooperativeLevel()函数;设置显示模式你就调用IDirectDraw7::SetDisplayMode()函数。就这么简单!先来看看协作级别。这就是函数原形:

HRESULT SetCooperativeLevel(
    HWND hWnd,
    DWORD dwFlags
);


返回的类型是HRESULT,你应该已经熟悉它了。对于所有的DirectX函数调用,你都可以用SUCCEEDED()和FAILED()宏检测调用的结果。以下是函数SetCooperativeLevel()的参数:
HWND hWnd:很熟悉吧!传递主窗口的句柄给它,使Windows知道谁将使用它的资源。
DWORD dwFlags:这个也很眼熟吧!每次我们看到dwFlags参数,几乎都有一个大的标志常量列表供我们选择,并且可以用“|”组合。这次也不会让你失望的哦!
◎ DDSCL_ALLOWMODEX:启用Mode X 显示模式(如320×200,320×240或者320×400)。该标志只能用于DDSCL_EXCLUSIVE和DDSCL_FULLSCREEN模式。
◎ DDSCL_ALLOWREBOOT:在独占模式中启用Ctrl+Alt+Del组合键功能。
◎ DDSCL_EXCLUSIVE:请求独占模式,必须与DDSCL_FULLSCREEN同时使用。
◎ DDSCL_FULLSCREEN:独占模式的拥有者负责整个主表面,GDI被忽略,必须与DDSCL_EXCLUSIVE同时使用。
◎ DDSCL_NORMAL:表示常规的Windows应用程序,不能与DDSCL_ALLOWMODEX、DDSCL_EXCLUSEIVE或DDSCL_FULLSCREEN标志同时使用,在该模式下运行的应用程序不能进行页交换或者更改主调色板。
◎ DDSCL_NOWINDOWCHANGES:防止DirectDraw最小化或恢复应用程序窗口。
还有几个标志常量我们暂时用不到,就不说了。由于我们要建立一个全屏的640×480×16的显示模式,所以我们得这样设置:

lpdd7->SetCooperativeLevel(hwnd, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);

现在协作级别已经设置好了,让我们再看看改变显示模式的函数:

HRESULT SetDisplayMode(
    DWORD dwWidth,
    DWORD dwHeight,
    DWORD dwBPP,
    DWORD dwRefreshRate,
    DWORD dwFlags
);


别忘了用宏去检测调用函数的成功或失败!大多数的参数同你料想的差不多:
DWORD dwWidth,dwHeight:以象素为单位,新显示模式的尺寸。
DWORD dwBPP:新显示模式的色彩深度。就是每一个象素有多少位字节。可以设置为8,16,24或32。警告:很多显示卡不支持24-bits。
DWORD dwRefreshRate:屏幕的刷新频率。但你最好设置为0,使用默认的刷新频率。
DWORD dwFlags:对不起,这次没有列表了^_^,唯一的选择是DDSDM_STANDARDVGAMODE,它把显示模式设置为0x13(DOS程序员的好朋友),取代了Mode X的320×200×8的模式。如果你还想使用其它的模式(你可能经常需要),没有问题,把它设置为0好了。
这些就是显示模式的设置,事先最好了解你的显示卡支持的显示模式,它们通常都支持640×480,800×600,1024×768等等,这些都是标准的模式。但是如果你非得设置成542×366的模式,你可能就会得到错误的反馈。科技在发展吗,什么都是可能的。让我们继续吧!

☆ 创建表面
这一次,我们需要比调用一个函数多一点点的东东。创建表面不是很难的,实际上,也是由一个单独的函数完成的,但是首先你要填充一个描述你所要创建的表面的结构。给你看这个结构之前,我只想告诉你,你不必填满所有的成员。^_^这就是它,DDSURFACEDESC2:

typedef struct _DDSURFACEDESC2 {
    DWORD dwSize;
    DWORD dwFlags;
    DWORD dwHeight;
    DWORD dwWidth;

    union
    {
        LONG lPitch;
        DWORD dwLinearSize;
    } DUMMYUNIONNAMEN(1);

    DWORD dwBackBufferCount;

    union
    {
        DWORD dwMipMapCount;
        DWORD dwRefreshRate;
    } DUMMYUNIONNAMEN(2);

    DWORD dwAlphaBitDepth;
    DWORD dwReserved;
    LPVOID lpSurface;
    DDCOLORKEY ddckCKDestOverlay;
    DDCOLORKEY ddckCKDestBlt;
    DDCOLORKEY ddckCKSrcOverlay;
    DDCOLORKEY ddckCKSrcBlt;
    DDPIXELFORMAT ddpfPixelFormat;
    DDSCAPS2 ddsCaps;
    DWORD dwTextureStage;
} DDSURFACEDESC2, FAR *LPDDSURFACEDESC2;


坦率的说,编写DirectDraw的应用程序其实并不难。但是事情往往是这样,80%的工作只需要我们花费20%的时间就可以完成,而剩下的20%的工作却需要我们花费80%的时间来完成。DirectDraw编程比这还要严重,就笔者的看法,至少90%的工作只需要我们不到10%的时间来完成,而剩下的不到10%的工作却至少需要我们90%的时间!结构DDSURFACEDESC就是10%的一部分,它较为复杂,它嵌套了其它的结构。让我们看看这个怪物到底做了什么。我只说说重点的部分:
DWORD dwSize:任何DirectX结构都有dwSize这个成员,表示结构的大小。有了它,当函数接收到指向这些结构的指针时,就可以测定结构的大小了。
DWORD dwFlags:太好了,又有一大堆标志常量了^_^ !这些标志告诉接收函数哪些数据成员是有效的。要想使需要的数据成员有效,就必须传递相对应的标志常量给dwFlags,你当然可以用“|”组合它们。以下是列表:
◎ DDSD_ALL:所有的数据成员都有效。
◎ DDSD_ALPHABITDEPTH:表示数据成员dwAlphaBitDepth有效。
◎ DDSD_BACKBUFFERCOUNT:表示数据成员dwBackBufferCount有效。
◎ DDSD_CAPS:表示数据成员ddsCaps有效。
◎ DDSD_CKDESTBLT:表示数据成员ddckCKDestBlt有效。
◎ DDSD_CKDESTOVERLAY:表示数据成员ddckCKDestOverlay有效。
◎ DDSD_CKSRCBLT:表示数据成员ddckCKSrcBlt有效。
◎ DDSD_CKSRCOVERLAY:表示数据成员ddckCKSrcOverlay有效。
◎ DDSD_HEIGHT:表示数据成员dwHeight有效。
◎ DDSD_LINEARSIZE:表示数据成员dwLinearSize有效。
◎ DDSD_LPSURFACE:表示数据成员lpSurface有效。
◎ DDSD_MIPMAPCOUNT:表示数据成员dwMipMapCount有效。
◎ DDSD_PITCH:表示数据成员lPitch有效。
◎ DDSD_PIXELFORMAT:表示数据成员ddpfPixelFormat有效。
◎ DDSD_REFRESHRATE:表示数据成员dwRefreshRate有效。
◎ DDSD_TEXTURESTAGE:表示数据成员dwTextureStage有效。
◎ DDSD_WIDTH:表示数据成员dwWidth有效。
DWORD dwheight,dwWidth:表示要创建表面的尺寸。以象素为单位。
LONG lPitch:这个需要好好解释一下。lPitch表示从画面一行行首数据到下一行行首数据的距离,以字节为单位。例如,640×480×16,每一行有640个象素,每个象素需要两个字节装颜色的信息,所以pitch应该是1280个字节,对不对?可能有一些显示卡要多于1280,这每行多于的内存没有装置任何的图形数据,但是防备有些显示卡不能在线性内存模式显示图形,你还是把多于地放在那吧。这种情况很少发生,但你最好还是考虑在内。
LPVOID lpSurface:指向表面内存开始地址的指针。不管你使用什么显示模式,你都可以用DirectDraw创建的线性地址模式操作表面象素。要想这样,你必须锁住表面,但这已经超出我们现在所学的了。
DWORD dwBackBufferCount:后缓冲区的数目。以后我们会在提到它。
DWORD ddckCKDestBlt,ddckCKSrcBlt:前者为描述位转换操作的目标颜色值,后者是源颜色值。我们将在以后的文章中具体介绍。
DDPIXELFORMAT ddpfPixelFormat:这个结构包含了描述显示模式的象素格式标识符。以后会具体介绍,现在就不多说了。
DDSCAPS2 ddsCaps:这是最后一个重要的结构。它是一个充满控制标志的结构。感谢菩萨,这是一个小结构,结构成员中只有一个很重要。让我们看一看:

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中的位图。精彩在后面哦!请耐心期待。
待续。。。。。。

我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 游戏编程起源(初学者)Ⅷ

 ■ [欢迎对本文发表评论]
用  户:  匿名发出:
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。

最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接  
Copyright ©2001-2006 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00212