Windows绘图原理

我们在Windows环境下看到各种元素,如菜单、按钮、窗口、图像,都是“画”出来的。这时的屏幕,就相当于一块黑板,而Windows下的各种GDI要素,如画笔、画刷等,就相当于彩色粉笔了我们在黑板上手工画图时,是一笔一划的,电脑亦然。只不过电脑的速度比手工快的太多,所以我们看起来好像所有的图形文字都是同时出现的。

当要绘制太复杂图形(比如位图)时,电脑便力不从心了。这时的画面会显示的很慢,对于运动的画面,会给用户“卡住、闪烁”的感觉。

双缓冲绘制技术原理

双缓冲的原理可以这样形象的理解:把电脑屏幕看作一块黑板。

首先我们在内存环境中建立一个“虚拟“的黑板

然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕的时候

一次性的把内存中绘制好的图形“拷贝”到另一块黑板(屏幕)上。

采取这种方法可以提高绘图速度,极大的改善绘图效果。

双缓冲绘制技术实现步骤

第一步:

使用CreateCompatibleDC创建一个内存兼容DC,,但这个DC尺寸很小,通常是1*1像素,不能直接绘制

第二步:

使用CreateCompatibleBitmap创建位图,默认是全黑的,使用SelectObject将位图选入到兼容DC,

这时位图尺寸大小就相当于了内存设备环境尺寸大小,此时才可绘制。

第三步:

使用绘图API函数(RectangleMoveToEx等)在内存兼容DC上绘制各种图形

第四步:

使用BitBlt(不拉伸)StretchBlt(拉伸)将兼容DC一次性复制到窗口DC上

示例代码:(以下是 窗口过程中消息的分支)

case WM_PAINT:
{
	PAINTSTRUCT ps;//绘图结构体
	HDC hdc=BeginPaint(hwnd, &ps);
	

	//第一步:=创建一个内存兼容DC,此时它的大小是1*1,很小,不能绘制
	HDC hMenDC = CreateCompatibleDC(hdc);


	//第二步:创建兼容位图,提供绘画区域
	HBITMAP hMenBmp = CreateCompatibleBitmap(hdc, 100, 100);
	//并且把兼容位图选到兼容内存DC中,此时DC的大小与位图一致,可以绘制
	SelectObject(hMenDC, hMenBmp); 


	//第三步:在内存兼容DC上绘制各种图形
	SetTextColor(hMenDC,RGB(255, 0, 0));
	TextOut(hMenDC, 0, 0, TEXT("这是一个简单的绘图例子"), lstrlen(TEXT("这是一个简单的绘图例子")));
	Rectangle(hMenDC, 30, 30, 80, 80);


	//第四步 把内存中的图像一次性画到窗口DC上

	//不拉伸
	BitBlt(hdc, 0, 0, 100, 100, hMenDC, 0, 0,SRCCOPY);
	//拉伸
	StretchBlt(hdc,0, 100, 200, 200, hMenDC, 0, 0, 100, 100, SRCCOPY);
	//缩放
	StretchBlt(hdc, 300, 0, 50, 50, hMenDC, 0, 0, 100, 100, SRCCOPY);


	//最后不要忘记释放资源
	DeleteDC(hMenDC);
	DeleteObject(hMenBmp);


	EndPaint(hwnd,&ps);
	break;
}





扩展阅读:

BitBlt(不拉伸)函数介绍:执行对应于从指定的源设备上下文像素矩形到目标设备上下文的颜色数据的位块传输。BOOL BitBlt(

HDC    hdcDest,//目标设备上下文的句柄。

int    nXDest,//目标矩形左上角的x坐标。

int    nYDest,//目标矩形左上角的y坐标。

int    nWidth,//目标矩形、源矩形的宽度

int    nHeight,//目标矩形、源矩形的高度

HDC    hdcSrc,//源设备上下文的句柄。

int    nXSrc,//源矩形左上角的x坐标

int    nYSrc,//源矩形左上角的y坐标

DWORD dwRop//光栅操作代码。这些代码定义如何将源矩形的颜色数据与目标矩形的颜色数据组合以实现最终颜色。

) ;

光栅操作代码可选值:


BLACKNESS    使用物理调色板中与索引0关联的颜色填充目标矩形(对于默认物理调色板为黑色)

CAPTUREBLT    包括在结果图像中窗口顶部的任何窗口。默认情况下,图像只包含你的窗口。

DSTINVERT    颠倒目标矩形。

MERGECOPY    通过使用布尔AND运算符,将源矩形的颜色与当前在hdcDest中选择的画笔合并。

MERGEPAINT    通过使用布尔或运算符将反转源矩形的颜色与目标矩形的颜色合并。

NOMIRRORBITMAP    防止镜像被镜像。

NOTSRCCOPY    将倒置的源矩形复制到目标。

NOTSRCERASE    通过使用布尔OR运算符组合源矩形和目标矩形的颜色,然后反转结果颜色。

PATCOPY    将当前在hdcDest中选择的画笔复制到目标位图中。

PATINVERT    通过使用布尔XOR运算符,将当前在hdcDest中选择的画笔的颜色与目标矩形的颜色组合在一起。

PATPAINT    此操作的结果通过使用布尔或运算符与目标矩形的颜色相结合。

                        通过使用布尔OR运算符,将当前在hdcDest中选择的画笔的颜色与反转的源矩形的颜色组合。

SRCAND    通过使用布尔AND运算符组合源和目标矩形的颜色。

SRCCOPY    将源矩形直接复制到目标矩形。(通常选用这个)

SRCERASE    通过使用布尔AND运算符将目标矩形的反转颜色与源矩形的颜色组合在一起。

SRCINVERT    通过使用布尔XOR运算符组合源和目标矩形的颜色。

SRCPAINT    通过使用布尔或运算符组合源和目标矩形的颜色。

WHITENESS    便用物理调色板中与索引1关联的颜色填充目标矩形。(对于默认物理调色板为白色)



如果函数或功,返回值为非零。

如果函数失败,返回值为零,调用GetLastError获得扩展的错误信息.

StretchBlt(拉伸)函数介绍


BOOL StretchBlt (

HDC    hdcDest,    //目标设备上下文的句柄。

int    nXDest,    //目标矩形左上角的x坐标。

int    nYDest,    //目标矩形左上角的y坐标。

int    nWidth,    //目标矩形的宽度

int    nHeight,    //目标矩形的高度

HDC    hdcSrc,    //源设备上下文的句柄。

int    nXSrc,    //原矩形左上角的x坐标

int    nYSrc,    //源矩形左上角的y坐标

int    nWidthSrc,    //源矩形的宽度    比BitBlt 多了这两个参数

int    nHeightSrc,    //源矩形的高度    比BitBlt 多了这两个参数

DWORD dwRop    //光栅操作代码。这些代码定义如何将源矩形的颜色数据与目标矩形的颜色数据组合以实现最终颜色。

) ;

如果函数或功,返回值为非零。

如果函数失败,返回值为零,调用GetLastError获得扩展的错误信息.