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获得扩展的错误信息.



相关推荐

c/c++ gdi绘制(可替代片框组件) 以及片失真 解决方法

位图图像(Bitmap),亦称为点阵图像或绘制图像,是由称作像素(图片元素)的单个点组成的。BMP文件的图像深度(用多少个二进制位来表示每个点的颜色)可选1bit、4bit、8bit及24bit,BM

自绘gdiplus基础:gdigdi+的区别、设备环境dc的概念、以及对象的使用方法

gdi和gdi+的区别1.GDI是gdi32.dll这个库,而GDI+是GDIplus.dll这个库2.GDI是硬件加速的,而GDI+不是3.GDI是有状态的,而GDI+是无状态的4.GDI绘图要使用

74Hc245芯片的作用 引脚以及功能 (解决单片机输出功不足的问题)

以下仅为简单总结,详情请参阅购买开发板附带的资料作用: 由于单片机输出的功率不足,所以可以通过74HC245来增强他的电流上限功能:八个输入信号原封不动的输出,只不过可接的电流更大一些。可解决led太

PHP技术OB系统函数(总结)(转载)

原文地址:https://www.bbsmax.com/A/x9J2vXWVJ6/一句话总结:ob相比于php普通的文件操作多了缓存机制,所以适合做php的页面静态缓存1、为什么php使用ob做静态文

文本_逐字分割 正则表达式效率对比

在同样处理10000条数据的时候文本_逐字分割 耗时 94毫秒正则表达式 耗时 7488毫秒所以 文本_逐字分割比正则表达式效率高可见其实正则表达式效率是很慢的

mysql效率研究(二):char(20) char(40) varchar(255)和varchar(256) varchar(50)和varchar(100) 的区别

/*varchar(255)和varchar(256) 和 varchar(50)和varchar(100) 的区别*/ $sql="create table char20(

mysql效率研究(一):int(5)与 int(10) int(11) 的区别

/*int(5)与 int(10) 与 int(11) 的区别*/ //首先创建 三个表 分别是 in5,in10,in11 都只有一个字段 $sql="create table

html复选框checkbox的使用, 未选中也是on的问题,原生JavaScript操作checkbox

html代码:已改成html<label for="myCheckbox">点击我</label>JavaScript代码:document.getElem

zblog小程序APi 正文不显示问题

第一处代码: 解决文章页面 文章内容是空的问题\\zb_system\\api\\post.php搜索 $post->LoadInfoByID($postId) 并在后面加入 以下代码 //解决

同服务器域名混乱问题 $_SERVER['HTTP_HOST'];

一般来说,这样子不会遇到什么问题,在一些常见的php框架中,如PFC3和FLEA也是基于该预定义变量。然而最近在做的一个项目,程序移交到客户手里测试时,竟然发现程序的跳转总是会出错。最后找出原因:$_