使用Blitter
DirectDraw中在各个表面之间进行Blitter和Windows编程中的各个DC之间Blt有点类似,不过DirectDraw中可以做的更加好,更加快。有两个达到这个功能的函数:Blt() 和 BltFast()。他们的不同是前者会调用裁减器而后者不用但是速度更快。
示例代码:
DDBLTFX ddbltfx;
RECT dest_rect;
memset(&ddbltfx, 0, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillColor = RGB(0, 0, 0); // or color index in 8 bit mode
dest_rect.left = x1;
dest_rect.top = y1;
dest_rect.right = x2;
dest_rect.bottom = y2;
lpddsprimary->Blt(&dest_rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);在上面的例子中,调用Blt函数有两个参数是NULL,因为这个例子比较特殊,他并没有从另外一个已有表面复制,而是用一种颜色对自己进行填充。这是Blt的一个特殊用法。一般情况下,我们总是从另外一个表面(可能是离屏表面)向目标表面(可能是后备缓冲)进行填充。注意,函数调用的参数中的那个表面是源表面。
上面Blt函数中的第一个NULL参数表示源表面要复制过来的区域,那么要是这块区域对应到目标表面的区域出现了问题怎么办?也就是说,他超出了整个目标表面。如要从源(0,0, 100, 100)复制到目标的(600, 400, 700, 600)(这里保持两个RECT大小一样,不一样的情况以后会说),但是目标表面只有640*480的大小,也就是说没有(700,600)这点,有一部分会超出表面。所以这个时候我们只要复制(600, 400, 640, 480)这样一块就可以了。其余部分需要裁减掉。
裁减器
你需要做的就是创建一个IDirectDrawClipper,传给它有效的裁减区域,然后将它同表明连接。具体步骤如下:
创建DirectDraw裁减器对象。 创建裁减序列。 用IDIRECTDRAWCLIPPER::SetClipList() 将裁减序列发送给裁减器。 用IDIRECTDRAWSURFACE7::SetClipper()将裁减器同窗口和/或表面相关联。示例代码:
LPDIRECTDRAWCLIPPER lpddclipper = NULL;
lpdd->CreateClipper(0, &lpddclipper, NULL);
lpddclipper->SetClipList(&rgndata, 0);
lpddsurface->SetClipper(&lpddclipper);其中的rgndata变量是一个RGNDATA结构,这是一个动态的结构。由两个成员(一个结构,一个指针)组成。用这个结构来创建裁减序列。
离屏表面
接下来我们说一下离屏表面(通用的非主表面也非后备表面)的创建。
基本同创建主表面一样,只是对于ddsd结构的设置稍有以下不同。
- 你必须将ddsd.dwFlags设置为 DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT
- 你必须在ddsd.dwWidth, ddsd.dwHeight中设置所请求的表面的尺寸。
- 必须将ddsd.dwCaps设置为DDSCAPS_OFFSCREENPLAIN | memory_flags,其中memory_flags决定在那里创建表面。
示例代码:
LPDIRECTDRAWSURFACE lpdds;
DDRAW_INIT_STRUCT(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.dwWidth = 1024;
ddsd.dwHeight = 768;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
lpdd->CreateSurface(&ddsd, &lpdds, NULL);这样就创建了一个和主表面兼容的离屏表面。另外建议在创建离屏表面的时候总是从大到小的创建。
现在你就可以像使用一般的表面一样来进行锁定,位图复制和Blitter操作了。
色彩键
当我们在复制位图的时候可能其中的某些颜色(透明色)我们并不想复制。那么我们就可以通过将他们设置成源色彩键。例如我们要把色彩0作为色彩键,可以这么做:
示例代码:
DDCOLORKEY color_key;
color_key.dwColorSpaceLowValue = 0;
color_key.dwColorSpaceHighValue = 0;
lpdds->SetColorKey(DDCKEY_SRCBLT, &color_key);