前言:
为什么需要使用双缓冲技术?可能很多朋友会问,不知道你们有没有发现,当屏幕刷新的时候会有闪烁,这样让人的体验感极差。原因是绘图与显示器刷新不同步,有时间差,为解决这一问题,这就需要用到双缓冲技术来绘图了。双缓冲技术是相对单缓冲而言的,单缓冲就是直接在设备DC上绘图;而双缓冲就是先在一个与设备DC相兼容的内存缓冲区里进行绘图,然后再一次性复制到设备DC上。一次性在屏幕上显示就不会出现闪烁的现象。
这里需要注意的是:我们创建的兼容DC,不能直接在上面绘图,这里还需要一块画布,那我们创建的兼容DC就相当于画板,有了画板、画布,将画布选放在画板兼容DC上就可以进行绘图了。然后一次性贴在设备DC上就搞定了。如下:
HDC mdc=CreateComatibleDC(hdc); // 创建兼容DC 画板
HBITMAP bmp=CreatrCompatibleBitnap(hdc,600,600); // 创建画布
SelectObject(mdc,bmp); // 将画布选入画板
一、双缓冲技术的使用
双缓冲绘图步骤:
- 在内存中创建兼容DC缓冲区(依次包括创建兼容DCCreateComatibleDC、创建画布CreatrCompatibleBitnap、将画布选入SelectObject)。
- 在缓冲区进行画图操作(可以画图形、也可以贴位图)。
- 将兼容缓冲区一次性复制到设备DC上。(复制用Bitblt函数)
- 释放内存缓冲区。(DeleteDC函数)
几个关键API函数:
CreateCompatibleDC:
该函数创建一个与指定设备兼容的内存设备上下文环境(DC)
HDC CreateCompatibleDC(HDC hdc);
CreateCompatibleBitmap:
该函数创建与指定的设备环境相关的设备兼容的位图.
HBITMAP CreateCompatibleBitmap(HDC hdc,
int nWidth, // 定位图的宽度,单位为像素
int nHeight);// 指定位图的高度,单位为像素
BitBlt:
BitBlt是一个计算机函数,该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境.
BOOL BitBlt( _In_ HDC hdcDest,
_In_ int nXDest, // 指定目标矩形区域左上角的X轴逻辑坐标
_In_ int nYDest, // 指定目标矩形区域左上角的Y轴逻辑坐标
_In_ int nWidth, // 指定源在目标矩形区域的逻辑宽度
_In_ int nHeight, // 指定源在目标矩形区域的逻辑高度
_In_ HDC hdcSrc, // 指向源设备环境的句柄
_In_ int nXSrc, // 指定源矩形区域左上角的X轴逻辑坐标
_In_ int nYSrc, // 指定源矩形区域左上角的Y轴逻辑坐标
_In_ DWORD dwRop); //指定光栅操作代码。这些代码将定义源矩形区域的颜色数据,如何与目标矩形区域的颜色数据组合以完成最后的颜色。
单双缓冲技术操作对比:
单缓冲技术绘制两个矩形:
// 直接在设备DC上绘制
Rectangle(hdc, 100, 100, 200, 200);
Rectangle(hdc, 300, 300, 200, 200);
双缓冲技术绘制两个矩形:
// 1.创建兼容缓冲区
mdc = CreateCompatibleDC(hdc); // 创建兼容DC
bmp = CreateCompatibleBitmap(hdc, 600, 600); // 创建兼容位图画布
SelectObject(mdc, bmp); // 选入
// 2.在缓冲区绘制
Rectangle(mdc, 100, 100, 200, 200);
Rectangle(mdc, 300, 300, 200, 200);
// 3.一次性复制到设备DC
BitBlt(hdc, 0, 0, 500, 500, mdc, 0, 0, SRCCOPY);
// 4.释放缓冲区DC
DeleteDC(mdc);
二、绘制位图
绘制位图步骤:
- 创建兼容DC(CreateCopatibleDC函数)
- 加载位图(LoadImage函数和LoadBitmap函数)
- 选取位图对象,使用BitBlt函数进行贴图(SelectObject函数)
- 释放兼容DC(DeleteDC函数)
加载位图API函数:
第一种 :LoadImage
LoadImage是一种函数,功能是装载图标,光标,或位图。
HANDLE LoadImage(HINSTANCE hinst,// 处理包含被装载图像模块的实例句柄。若要装载OEM图像,则设此参数值为0。
LPCTSTR lpszName,// 图像资源名称
UINT uType, // 指定被装载图像类型,IMAGE_BITMAP:装载位图;IMAGE_CURSOR:装载光标;IMAGE_ICON:装载图标。
int cxDesired,// 指定图标或光标的宽度,以像素为单位
int cyDesired,// 指定图标或光标的高度,以像素为单位
UINT fuLoad);// 加载标识,含义见链接
第二种 :LoadBitmap
该函数从模块的可执行文件中加载指定的位图资源,该函数已经被函数LoadImage替代。
HBITMAP LoadBitmap(HINSTANCE hInstance, LPCTSTR lpBitmapName);
注意: 在内存DC上绘制位图时也需要创建一个与窗口DC兼容的内存DC(maphdc),还需要一个HBITMAP map来加载位图,然后选用位图对象( SelectObject(maphdc,map)与之前画笔画刷选取一样),最后用BitBlt函数将位图贴入内存DC上。
上面所说的BitBlt函数是指在内存DC上贴位图,其中包括在设备DC和双缓冲技术的缓冲DC.在双缓冲技术绘制位图时,需要特别注意的是:兼容DC我们创建了两个(mdc和maphdc),mdc是真正的缓冲区(开始将所有图形位图都绘制在这个缓冲DC中),而maphdc是在选取位图时用的,会有很多人理解错,我开始学的时候也有点。HBITMAP 我们也声明了两个(bmp和map),bmp是mdc的画布(需要用CreateCompatibleBitmap来创建),而map只是用来加载位图的。以下做个对比说明:
单缓冲绘制位图:
// 1.创建兼容DC
maphdc = CreateCompatibleDC(hdc);
// 2.加载位图
HBITMAP map = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 500, 500, LR_CREATEDIBSECTION);
// 3.选取位图对象,使用BitBlt函数贴图
SelectObject(maphdc, map);
BitBlt(hdc, 0, 0, 1500, 1500, maphdc, 0, 0, SRCCOPY);
// 4.释放兼容DC
DeleteDC(maphdc);
双缓冲绘制位图:
// 1.创建兼容缓冲区
mdc = CreateCompatibleDC(hdc); // 创建兼容DC
bmp = CreateCompatibleBitmap(hdc, 600, 600); // 创建兼容位图画布
SelectObject(mdc, bmp); // 选入
// 2.在缓冲区绘制
maphdc = CreateCompatibleDC(hdc); /*创建兼容DC*/
/*贴第一张位图*/
HBITMAP map = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 500, 500, LR_CREATEDIBSECTION);
SelectObject(maphdc, map);
BitBlt(mdc, 0, 0, 500, 500, maphdc, 0, 0, SRCCOPY);
/*贴第二张位图*/
HBITMAP map = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 500, 500, LR_CREATEDIBSECTION);
SelectObject(maphdc, map);
BitBlt(mdc, 0, 0, 500, 500, maphdc, 0, 0, SRCCOPY);
DeleteDC(maphdc); /*释放兼容DC*/
// 3.一次性复制到设备DC
BitBlt(hdc, 0, 0, 500, 500, mdc, 0, 0, SRCCOPY);
// 4.释放缓冲区DC
DeleteDC(mdc);
来源:CSDN
作者:小小妖妖
链接:https://blog.csdn.net/qwq1503/article/details/103473160