ok,然后就是设置显示模式的函数,它的原型是:
HRESULT SetDisplayMode(
DWORD dwWidth,
DWORD dwHeight,
DWORD dwBPP,
DWORD dwRefreshRate,
DWORD dwFlags
);
dwWidth and dwHeight用来设置显示模式的宽度和高度。
dwBPP用来设置显示模式的颜色位数。
dwRefreshRate设置屏幕的刷新率,0为使用默认值。
dwFlags现在唯一有效的值是DDSDM_STANDARDVGAMODE。
创建页面,先清空,申请空间(类似于c中的析构函数)
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));//开始创建主页面,先清空页面描述
ddsd.dwSize = sizeof( ddsd );//填充页面描述
ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT; //有后台缓存
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1; //一个后台缓存
lpDD-CreateSurface( &ddsd, &lpDDSPrimary, NULL ); //创建主页面
创建主页面的函数原型是:
HRESULT CreateSurface(
LPDDSURFACEDESC2 lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE FAR *lplpDDSurface,
IUnknown FAR *pUnkOuter
);
第一个参数是被填充了页面信息的DDSURFACEDESC2结构的地址,此处为&ddsd;
第二个参数是接收主页面指针的地址,此处为&lpDDSPrimary;
第三个参数现在必须为NULL,为该函数所保留。
后面创建放背景和鼠标的页面也是一个道理。
后面就是贴图,把要显示的图片先贴出来,给一个指针指定其位置,后面要使用的的时候直接操作指针即可。不过在这之前还是要清空页面,最后贴好图后要设置图片的透明色,这样图片我们才可见。
//清空各个页面
DDBLTFX ddBltFx;
ddBltFx.dwSize=sizeof(DDBLTFX);
ddBltFx.dwFillColor=0;
lpDDSPrimary -Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);
lpDDSBuffer-Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);
lpDDSMap-Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);
lpDDSMouse-Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);
//贴图和设置透明色
DDReLoadBitmap(lpDDSMap,"inn.BMP");
DDReLoadBitmap(lpDDSMouse,"mouse.BMP");
MakeRect(0,0,640,480);
lpDDSPrimary-BltFast(0,0,lpDDSMap,&r,NoKey);
DDSetColorKey(lpDDSMap,RGB(0,255,0));
DDSetColorKey(lpDDSMouse,RGB(0,255,0));
写到这里,也该休息一下了。
reader:“这人怎么这样不负责任,总是写的没头没尾的!#$%*^*”
weter:“先卖个关子,下一篇章中我们会进入到具体的功能的实现上,到底是怎么样完成图片的裁减的工作的?他的原理是怎么样的?”
预听后事如何,且待下回分解。
第四回:
今天是最后一话了,而且废话了这么久都没有切入主题,偶对不住大家啦,今天我们就正儿八经的的进入这次我们这个冗长的故事的核心的部分了,同时也是最后一个部分。
书归正传,在direct编程里面有两个比较重要的函数,也是使用频率相当高的两个函数,在进入主题前我们必须先介绍这两个函数,我们这个程序里面也是用了他们。
第一个很有用的函数是BltFast(),他的原型是
HRESULT BltFast(
DWORD dwX,
DWORD dwY,
LPDIRECTDRAWSURFACE lpDDSrcSurface,
LPRECT lpSrcRect,
DWORD dwTrans
);
下面将逐一介绍这几个参数:
(1)dwX和dwY:图像将被传送到目标页面何处。
(2)lpDDSrcSurface:图像传送操作的源页面。目标页面就是调用此方法的页面。
(3)lpSrcRect:一个 RECT (Rectangle,即矩形)结构的地址,指明源页面上将被传送的区域。如果该参数是NULL,整个源页面将被使用。RECT结构在DirectDraw中非常常用,最好在程序中定义一个RECT类型的全局变量,如rect,再象这样写一个函数:void MakeRect ()(关于这个函数就是我说的第二个非常有用的函数,我们在后面在专门对他进行介绍和说明)。
(4)dwTrans:指定传送类型。有如下几种:
DDBLTFAST_NOCOLORKEY
指定进行一次普通的复制,不带透明成分。
DDBLTFAST_SRCCOLORKEY
指定进行一次带透明色的图像传送,使用源页面的透明色。
DDBLTFAST_WAIT
如果图像传送器正忙,不断重试直到图像传送器准备好并传送好时才返回。一般都使用这个参数。由于第四个参数比较长,而且有时候是两个搭配起来用,所以大多数时候都是定义两个全局变量,后面使用起来就比较方便。
DWORD SrcKey = DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT
DWORD NoKey = DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT
第二个很有用的函数就是我们前面提到的void MakeRect (),这一般是一个自定义函数,我们可以这样定义他:
void MakeRect (int left, int top, int right, int bottom)
{
rect.bottom = bottom;
rect.left = left;
rect.right = right;
rect.top = top;
}
主要是确定了这个r结构的四个边际。
所以要裁减一副图片到一个页面中就很简单了,是不是^_^,举个例子:我们要贴第一回的哪个背景到SPrimary这个主页面里,就可以这样
MakeRect(0,0,640,480);
lpDDSBuffer-BltFast(0,0,lpDDSPrimary,&r,NoKey);
核心部分
因为哪个背景的大小是640*480,所以我们的右边际是640,下边际是480,最后在利用BltFast()函数贴出来就是了,而且没有透明,这样我们就可以贴图了。
可是怎么样裁减呢?其实也就没什么难度了,你想在MakeRect()这个函数里面我们改变要贴图的大小不就可以贴同一幅图里任意位置的图部分了吗,这就是裁减了塞,然后我们设成变量,用鼠标自定义贴的大小,就必须和windows的消息循环机制联合起来使用了塞,我们在mousedown的时候得到他的一个坐标,在mouseup的时候得到他的另一个坐标,将两个坐标之间的图片贴出来就可以了塞。其实这个裁减程序的主要的核心技术就在这里了,实现思想也就是这么回事,简单吧:),其他的都是一些旁支末节的东西了。不过我们还是要一一介绍完。
ok,到这里我们就可以单独写一个类出来,完成我们的图片裁减和贴图功能了,我们写一个类叫draw.cpp,这里我们还把他的头文件draw.h写出来。
draw.h:
#if !defined (draw_h)
#define draw_h
class draw
{
public:
int x1;
int y1;
int x2;
int y2;
void Rectanglep(int x1, int y1, int width, int height);//做成一个鼠标在屏幕移动矩形的函数
void blt(int x1,int y1,int x2,int y2);//完成我们的图片裁减功能
};
#endif
draw.cpp:
#include "main.h"
void draw::blt(int x1,int y1,int x2,int y2)
{
x1=drawp.x1;
y2=drawp.y1;
x2=drawp.x2;
y2=drawp.y2;
MakeRect(x1,y1,x2,y2);
lpDDSBuffer-BltFast(0,0,lpDDSMap,&r,SrcKey);
}
void draw::Rectanglep(int x1,int y1,int x2,int y2)
{
HDC hdc;
lpDDSPrimary-GetDC(&hdc);//主页面得到句柄
HPEN Red_Pen=CreatePen(PS_SOLID,0,RGB(0,255,0));//填充画笔的颜色
SelectObject(hdc,Red_Pen);//设置画笔的类型
Line(x1,y1,x1,y2,hdc);//画线
Line(x1,y1,x2,y1,hdc);
Line(x2,y1,x2,y2,hdc);
Line(x1,y2,x2,y2,hdc);
lpDDSPrimary-ReleaseDC(hdc);//用完后释放句柄
}
这里就是对这两自定义函数的具体化了。
第一个函数就是我们前面介绍的实现图形的裁减的部分,而且定义了四个变量作为鼠标取点的坐标。
第二个函数就是鼠标在屏幕上运动画出的轨迹,是由四条线组成的一个矩形,这里用到了API函数作图,也就是微软给我们的函数(微软什么都给我们封装好了,用起来还真是方便呀)。
然后就是公共使用的函数的一个类,这里面自定义的函数可以全部被自由的使用
我们定义为
publicfuction.cpp
//direct的初始化,前面介绍过,可以参看前面的章节
void init()
{
DDSURFACEDESC2 ddsd;
DirectDrawCreateEx (NULL, (void **)&lpDD,IID_IDirectDraw7, NULL);
lpDD-SetCooperativeLevel(hwnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);
lpDD-SetDisplayMode( 640, 480, 32, 0, DDSDM_STANDARDVGAMODE );
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
lpDD-CreateSurface( &ddsd, &lpDDSPrimary, NULL );
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
lpDDSPrimary-GetAttachedSurface( &ddsd.ddsCaps, &lpDDSBuffer );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|D