在CB中举办DirectX编程(3)
副标题#e#
2.3 装入并显示图形文件
为了简明地说明回收DirectDraw图形文件的显示技能,我们以示例措施dx2先容图面、图形文件装入、图形缩放、图形在图面上显示等的劈头观念和实现技能。
2.3.1 DirectDraw显示图形的技能
为了显示图象,DirectDraw必须首先拥有雷同画布(canvas)的画图空间,DirectDraw并不向在DOS下那样简朴地将显示缓存作为绘画的工具,而是通过DirectDraw工具建设各类差异种类的“图面”(Suerface),图面上的内容可以被应用措施自由地拷贝、组合,生成千变万化的图形。
2.3.1.1图面分以下几种范例:
(1)主图面(Primary图面):即在屏幕上显示出来的图面,就是GDI用于绘制Windows用户界面的图面。每个DirectDraw工具只能有一个主图面,主图面的尺寸、位置和名目由系统当前的显示模式抉择,不能窜改。
(2)靠山图面(Off-screen图面):此类图面不能被直接看到。一般来说,靠山图面往往用于作为游戏精灵动画、配景图形等部件的存储缓冲区。靠山图面的尺寸是可以调解的,且可以有多个靠山图面,其巨细按照实际环境调解,不要太大或太小。一种典范的例子是:有一个精灵的动画由4张128点阵图形构成,那么可以将靠山图面界说为256点的方阵,将这个动画序列存储下来读者大概认为可以建设一个比主图面大的靠山图面以便生存游戏配景,这样可以利便地实现滚屏,可是,DirectDraw限制靠山图面的尺寸不能比主图面大,除非系统的显示卡支持。可否实现大的靠山图面我们将在今后论述。
(3)复合图面(Complex图面)和翻转链(Flipping Chain):这种图面主要用于生成滑腻动画。有关技能待建造动画时先容。
(4)包围图面(Overlay图面):这是一种由硬件支持的图面,DirectDraw不能仿真。有关技能在后头先容。
DirectDraw可以把图面建设在显示内存或系统内存中,而显示内存又分为通例显示内存和AGP加快图形接口内存。由于显示内存容量是有限的,所以每个图面详细应该建设在哪部门存储区域中应该统筹筹划,一般将利用频繁,需要硬件加快或实现成果的图面布置在显示内存。假如您不指定图面建设的位置,DirectDraw将首先在通例显示内存建设图面,当通例显示内存不足时,若系统支持AGP内存,则先利用AGP内存,最终利用系统内存。
2.3.1.2 图形文件的装入
图形文件装入到图面并不象想象的那么简朴,因为装入的图形的点阵大概与、图面的点阵差异,这就存在图形的缩放。别的,图形数据在内存中的移动、复制,也是需要处理惩罚的内容。对付Windows的设备无关位图,我们可以思量利用Windows的成果实现:
(1)回收LoadImage函数装入图形文件
(2)回收图面的GetDC要领得到图面与GDI兼容的设备上下文
(3)回收BitBlt函数将图形数据拷贝到图面中
有关GDI编程请参看有关Windows编程资料,这里读者只需要知道牢靠的用法就可以了。
2.3.1.3 图面的丢失
在DirectDraw应用措施被最小化、屏幕显示方法改变或用户按Alt+Tab键切换当前应用措施时,图面将会丢失,因此在从头回到DirectDraw应用措施中时,必须用Restore要领规复图面。遗憾的是,固然图面被规复了,但个中图形数据却丢失了,需要从头绘制。
2.3.2 dx2运行进程
启动dx2措施后,只有第一个“执行”按钮可以利用,按下该按钮后,系统将建设DirectDraw工具,并配置为800*600全屏幕显示方法;按顺序按下“建设主图面”、“建设
图2.2 dx2 装入并显示图形文件措施运行界面
靠山图面”按钮,别离建设对应屏幕显示的主图面和100*100点阵的靠山图面;按下“靠山图面装入图形”按钮,则图形文件view.bmp被一100*100点阵装入到靠山图面,屏幕上看不见图形;再按下“主图面装入图形”按钮,view.bmp以200*100点阵缩放后装入到主图面(屏幕)的(0,0)位置,此时图形显示在屏幕左上角;继承按“拷贝靠山图面到主图面”,将把靠山图面的100*100图形显示在屏幕的(200,0)位置,我们可以看到两副同样的图形以差异的缩放比例并排显示在屏幕左上方;按下“图面丢失”后,屏幕被配置成640*480的显示方法,屏幕上显示出的图形消失了;用“规复丢失的图面”按钮从头配置显示方法为800*600(必须规复显示方法,不然图面规复将会失败)并规复图面,此时,失去的图形在屏幕上仍然看不见;最后,按“从头显示图形”来从头绘制view.bmp,屏幕从头揭示原有的图形。
#p#副标题#e#
2.3.3 dx2措施的编程实现
2.2.2 dx1编程实现
启动C++ Builder后在窗口Form1中设计如图2.2的操纵界面,各工具相关属性配置如表2.3:
控件工具范例 控件工具名称 相关属性 属性值
TForm Form1 Caption DirectX 操练措施1
TLabel Label1 Caption 运行状态:
TLabel Label2 Caption 设备的列举
Tlabel Label3 Caption 显示模式DDraw2
TEdit Edit1 Text (空)
ReadOnly True
TGroupBox GroupBox1 Caption 状态
TCheckBox CheckBox6 Caption DDSCL_NOWINDOWCHANGES
Checked true
TButton Button1 Caption 执行
TButton Button2 Caption 建设主图面
Enabled False
TButton Button3 Caption 建设靠山图面
Enabled False
TButton Button4 Caption 靠山图面装入图形
Enabled False
TButton Button5 Caption 主图面装入图形
Enabled False
TButton Button6 Caption 拷贝靠山图面到主图面
Enabled False
TButton Button7 Caption 图面丢失:配置640*480方法
Enabled False
TButton Button8 Caption 规复已丢失的图面
Enabled False
TButton Button9 Caption 从头显示图形
Enabled False
表2.3 dx2控件工具属性配置一览表
2.3.3.1 建设主图面
用HRESULT IDirectDraw::CreateSurface来建设图面:
lpDD2->CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE FAR *lpDDSurface,
Iunknown FAR *pUnkOuter)
#p#分页标题#e#
(1)参数lpDDSurfaceDesc是一个志向DDSURFACEDESC布局的指针,DDSURFACEDESC布局的界说较量巨大,幸好一般只需要利用个中很少的一部门。布局DDSURFACEDESC的部门描写如表2.4所示:
布局成员
描写
DOWRD dwSize
DDSURFACE布局的尺寸。在利用此布局之前,此项数据必须用sizeof函数配置
DWORD dwFlags
节制符号。主要可以配置的符号为:
DDSD_CAPS、
DDSD_HEIGHT、
DDSD_WIDTH、
DDSD_BACKBUFFERCOUNT、
DDSD_PIXELFORMATDENG 等
DWORD dwHeight
图面高度。主图面不需要配置
DWORD dwWidth
图面宽度。主图面不需要配置
DDSCAPS ddsCaps
图面本领。DDSCAPS也是一个布局,在建设图面时需要配置其成员dwCaps的值,以便确定所建图面的性质。
DwCaps的取值主要有:
DDSCAPS_PRIMARYSURFACE:主图面
DDSCAPS_OFFSCREENPLAIN:靠山图面
DDSCAPS_COMPLEX:复合图面
DDSCAPS_FLIP:图面翻转链
DDSCAPS_OVERLAY:包围图面
DDSCAPS_VIDEOMEMORY:图面建设在显示内存
DDSCAPS_LOCALVIDMEM:利用通例显示内存
DDSCAPS_NONLOCALVIDMEM:利用AGP内存
DDSCAPS_SYSTEMMEMORY:图面建设在系统内存
表2.4 DDSURFACEDESC布局的部门成员说明
(2)参数lpDDSurface返回一个指向所建设图面的指针。
(3)参数pUnkOuter未利用,必须为NULL。
建设主图面需要以下步调:
(1)得到并配置DDSURFACEDESC布局的尺寸dwSize:ddsd.dwSize=sizeof(ddsd);
(2)简朴地配置ddsd.dwFlags=DDSD_CAPS;
(3)配置主图面符号:ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
(4)挪用CreateSurface要领建设图面。
2.3.3.2 建设靠山图面
靠山图面的建设与建设主图面基内情同,只是在DDDURFACEDESC布局中多给出一些信息。建设靠山图面需要以下步调:
(1) 得到并配置DDSURFACEDESC布局的尺寸dwSize:ddsd.dwSize=sizeof(ddsd);
(2) 配置ddsd.dwFlags=DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
(3) 配置靠山外貌的宽和高(dx2中设为100):ddsd.dwHeight=100; ddsd.dwWidth=100;
(4) 配置靠山图面符号:ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
(5)挪用CreateSurface要领建设图面。
2.3.3.3 图形文件的装入靠山图面和图形文件的装入主图面
图形文件的装入主要回收Windows的函数,固然利用C++Builder的TCavas工具打开图形文件要利便一些,可是在BitBlt时不足不变,因此dx2照旧选择了前者。
dx2在实现图形内存数据复制时回收了GDI,在DirectDrawSurface工具中有GetDC和ReleaseDC两个要领,以便取得HDC并挪用GDI。
HRESULT IDirectDrawSurface::GetDC(HDC FAR *hdc)
HRESULT IDirectDrawSurface::ReleaseDC(HDC hdc)
参数hdc是一个设备句柄。
BitBlt固然速度较量慢,可是兼容性好,可以或许支持差异的显示模式,并且可以或许自动举办名目转换。
2.3.3.4 靠山图面图形拷贝到主图面显示
这里同样利用了BitBlt,将靠山图面的数据复制到主图面并显示出来。
2.3.3.5 丢失图面及规复初始显示方法和图面
#p#分页标题#e#
在dx2中我们演示了当改变屏幕显示方法时,图面丢失的现象,而且说明白在图面丢失后可以用HRESULT IDirectDrawSurface::Restore()要领来规复图面,同时必须从头绘制图面上的图形。
Restore要领没有参数,可是若要乐陋习复已丢失的图面,必须屏幕显示方法从头规复到其初始的状态。
为了判定图面是否已经丢失,也可以利用HRESULT IDirectDrawSurface::IsLost()要领来举办检测,若返回值为DDERR_SURFACELOST则说明图面确实丢失了。在dx2中没有举办此判定,读者可以按照本身的领略修改dx2,实现规复图眼前首先举办图面是否丢失的判定。
2.3.4 dx2源措施
2.3.4.1 dx2主要文件的构成为:工程文件(dx2.bpr)、窗口文件(main.cpp)、头文件(main.h)、view.bmp。
2.3.4.2 头文件main.h
#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Dialogs.hpp>
#include "d:\tools\dx5sdk\sdk\inc\ddraw.h"
//---------------------------------------------------------------------------
char CR[]={13,10,0};
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TLabel *Label1;
TGroupBox *GroupBox1;
TMemo *Memo1;
TButton *Button2;
TButton *Button3;
TButton *Button4;
TButton *Button5;
TButton *Button6;
TButton *Button7;
TButton *Button8;
TButton *Button9;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall Button3Click(TObject *Sender);
void __fastcall Button4Click(TObject *Sender);
void __fastcall Button5Click(TObject *Sender);
void __fastcall Button6Click(TObject *Sender);
void __fastcall Button7Click(TObject *Sender);
void __fastcall Button8Click(TObject *Sender);
void __fastcall Button9Click(TObject *Sender);
private: // User declarations
LPDIRECTDRAW FAR lpDD;
LPDIRECTDRAW2 FAR lpDD2;
DDSURFACEDESC ddsd;
LPDIRECTDRAWSURFACE FAR lpDDPrimary,lpDDOffScreen;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};