即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

VC6.0双缓冲绘图和自绘控件

编程语言 zhwzhaowei 12℃ 0评论

使用VC做界面的时候,缺少绘图控件,一直在使用第三方控件TeeChart和MsChart,但是总有点不方便,无法做到自定义样式,在移植的时候也有麻烦,所以想自己做画图控件,那就需要先学MFC的绘图功能(GDI绘图),之后就需要有一块画布来画图,从网上了解到,可以从MFC已有的控件如按钮、编辑框、文本框和图片等派生自己的控件来画图。

1.双缓冲绘图原理

双缓冲绘图一是提高绘图效率,二是避免重绘时出现闪烁。

   

先来看看MFC封装的设备描述表类CDC和绘图对象类CGdiObject:

A.CDC类

MFC为我们提供了一个设备描述表的封装类CDC,其下派生出四个子类CPaintDC、CClientDC、CWindowDC和CMetaFileDC。

CPaintDC:用于在窗口客户区画图(仅在OnPaint消息响应函数中使用)

CClientDC:用于在窗口客户区画图(除OnPaint外的任何处理程序中)

CWindowDC:用于在窗口内任意地方画图,包括非客户区

CMetaFileDC:用于向GDI源文件画图

 

注意:

当我们通过定义类对象的方式使用时,不需要自己释放设备描述表,类的构造函数和析构函数会自动调用,释放设备描述表,如:

CPaintDC dc(this);

如果在堆上用new创建设备描述表,需要手动释放设备描述表,如:

CPaintDC *pDC = new CPaintDC(this);

Delete pDC;

B.CGdiObject类

 MFC提供绘图工具类的封装类CGdiObject,其下派生出6个子类,分别如下:

CPen:画笔

CBrush:画刷

CFont:字体

CBitmap:位图

CPalette:调色板

CRegion:区域


使用方法如下:

创建画笔:CPen  pen;

Pen.CreatePen(参数);

创建一个保存原GDI工具对象的指针:

CPen*pOldPen = dc.SelectObject(&pen);

绘图:

还原默认工具:

dc.SelectObject(pOldPen);

 

双缓冲绘图实现过程:

1) 创建兼容的内存DC;

2) 创建兼容位图;

3) 用兼容内存DC关联兼容位图;

4) 使用兼容内存DC绘图;

5) 将兼容内存DC拷贝到物理DC上;

6) 回收兼容位图和兼容内存DC,防止资源泄漏。

实现代码如下:

CClientDCdc(this);

 

//创建绘图区域

CRect rectClient;

GetClientRect(&rectClient);

 

//创建兼容内存DC

CDCMemDC;

MemDC.CreateCompatibleDC(&dc);

 

//创建兼容位图,使兼容内存DC与之关联,否则兼容内存DC是一个1*1的单色位图

CBitmapbitmap;

bitmap.CreateCompatibleBitmap(&dc,rectClient.Width(), rectClient.Height());

CBitmap*pOldBitmap = MemDC.SelectObject(&bitmap);

 

//背景画刷

CBrushbrush(RGB(255,255,255));

MemDC.FillRect(rectClient,&brush);

 

//使用MemDC绘图

 

//DC拷贝

dc.BitBlt(0,0,rectClient.Width(),rectClient.Height(),&MemDC,0,0,SRCCOPY);

MemDC.SelectObject(pOldBitmap);

 

注意:

1) 创建兼容内存DC和兼容位图时,尽量使用封装类CDC和CBitmap,在类的析构函数中会自动释放对象资源;

2) 新创建的兼容位图是空位图,底色是黑色,因此使用内存DC画图前要用FillRect填充绘图区域;

3) 使用内存DC后,当前窗口频繁刷新时还是可以看到闪烁很严重,这是因为每次窗口重绘时会擦除一次背景,屏蔽此操作即可,响应WM_ERASEBKGND消息,在OnEraseBkgnd函数中直接return TRUE,即不调用窗口自带的擦除背景函数。

 

2.派生自绘控件

基于CButton的自绘按钮画波形图步骤:

1)从CButton中派生自己的按钮类;

2)借助MFC类向导为自己的按钮类添加虚函数PreSubclassWindow和DrawItem,在PreSubclassWindow中设置按钮样式为自绘模式,在DrawItem中实现自绘的代码;

3)为自己的按钮类添加消息响应函数OnEraseBkgnd,里面直接return TRUE,屏蔽窗口自带的擦除背景函数;

4)在对话框类CXXXDlg中使用自己的按钮类,首先添加一个CButton按钮,添加成员变量,变量类型为自己的按钮类,在需要使用的地方使用即可。

转载请注明:CodingBlog » VC6.0双缓冲绘图和自绘控件

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情