您的位置:首页 > 其它

GDI双缓冲绘图

2016-06-25 21:50 330 查看
一、简介

在进行复杂图形绘制时,若直接在屏幕DC上进行绘制,则会出现明显的闪烁。闪烁产生的原因是当绘制的图形较为复杂时,图形绘制过程中就被刷新到屏幕上,导致结果断断续续地显示出来。双缓冲绘图的原理是在另开辟一块内存用于绘制,当所有绘制工作完成后将内存数据一次性拷贝到屏幕上。

双缓冲绘图步骤:

创建兼容DC(CreateCompatibleDC)

创建兼容位图(CreateCompatibleBitmap)

将兼容位图选入兼容DC(SelectObject)

在兼容DC中进行绘制工作

将兼容DC中的像素拷贝至屏幕DC(BitBlt)

从兼容DC中换出兼容位图(SelectObject)

删除兼容位图(DeleteObject)

删除兼容DC(DeleteObject)

二、实现:

演示程序绘制了从窗口中心发射的300条射线,为了凸显双缓冲的效果,特意在绘制每条线段时添加延时操作(sleep)。可以发现,若直接在屏幕DC上绘制,能够明显感觉到每条线段的绘制过程,而采用双缓冲则无此现象。

直接绘制代码:

void CtestBFDlg::OnBnClickedDirectDraw()
{
// TODO: 在此添加控件通知处理程序代码
CPen newPen;
CPen *pOldPen;
CBrush newBrush;
CBrush *pOldBrush;
CRect zcRect;
CDC *pDc;
CPoint cenpoint;
CPoint point;

pDc = Picture.GetDC();
Picture.GetClientRect(&zcRect);
newPen.CreatePen(PS_SOLID,1,RGB(0,255,0));//画笔
pOldPen = pDc->SelectObject(&newPen);
newBrush.CreateSolidBrush(RGB(255,255,255));//画刷
pOldBrush=pDc->SelectObject(&newBrush);

//绘制工作(直接在屏幕DC上作图)
pDc->FillRect(zcRect,&newBrush);
float radius=200;
float degree=0;
float x,y;
float cenx,ceny;
cenx=zcRect.Width()/2.0;
ceny=zcRect.Height()/2.0;
cenpoint.x=cenx;
cenpoint.y=ceny;
for(int i=0;i<300;i++)
{
pDc->MoveTo(cenpoint);
degree=2*PI/300*i;
point.x=radius*cos(degree)+cenx;
point.y=radius*sin(degree)+ceny;
Sleep(1);        //刻意延时以凸显效果
pDc->LineTo(point);
}
pDc->SelectObject(pOldPen);
pDc->SelectObject(pOldBrush);
newBrush.DeleteObject();
newPen.DeleteObject();
ReleaseDC(pDc);
}
双缓冲绘制代码:

void CtestBFDlg::OnBnClickedDFDraw()
{
// TODO: 在此添加控件通知处理程序代码
CPen newPen;
CPen *pOldPen;
CBrush newBrush;
CBrush *pOldBrush;
CRect zcRect;
CDC *pDc;
CPoint cenpoint;
CPoint point;
pDc = Picture.GetDC();
Picture.GetClientRect(&zcRect);

CDC dc;
dc.CreateCompatibleDC(pDc);//创建兼容DC
CBitmap memBmp;
memBmp.CreateCompatibleBitmap(pDc, zcRect.Width(), zcRect.Height());//创建兼容位图
CBitmap* OldBmp = dc.SelectObject(&memBmp);//将位图选入DC

newPen.CreatePen(PS_SOLID,1,RGB(255,0,0));
pOldPen = dc.SelectObject(&newPen);
newBrush.CreateSolidBrush(RGB(255,255,255));
pOldBrush=dc.SelectObject(&newBrush);

//绘制工作(在兼容DC中作图)
//****************************************************************
dc.FillRect(zcRect,&newBrush);
float radius=200;
float degree=0;
float x,y;
float cenx,ceny;
cenx=zcRect.Width()/2.0;
ceny=zcRect.Height()/2.0;
cenpoint.x=cenx;
cenpoint.y=ceny;
for(int i=0;i<300;i++)
{
dc.MoveTo(cenpoint);
degree=2*PI/300*i;
point.x=radius*cos(degree)+cenx;
point.y=radius*sin(degree)+ceny;
Sleep(1); //此处刻意延时以凸显效果
dc.LineTo(point);
}
//****************************************************************
pDc->BitBlt(0,0,zcRect.Width(),zcRect.Height(),&dc,0,0,SRCCOPY);//将兼容DC中位图拷贝至屏幕DC
dc.SelectObject(pOldPen);
dc.SelectObject(pOldBrush);
dc.SelectObject(OldBmp);
newBrush.DeleteObject();
newPen.DeleteObject();
memBmp.DeleteObject();
dc.DeleteDC();
ReleaseDC(pDc);
}



界面:



源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: