最近用VC做了一个画图的控件。控件在使用的时候遇到点问题。在控件里画了图之后切换到其他页面,等再切换回来的时候,发现控件里画的图都不见了。这是因为VC里面,当缩小、遮挡页面后客户区域就会失效,当再次显示的时候系统就自动调用OnDraw 函数进行重绘。所以原来保存的图形都消失了。由于我做的是控件,所以不可能用一般的方法来解决比如在OnDraw 函数里绘图。经过这种查找决定使用双缓冲绘图来解决这个问题。

普通的绘图是直接将图像绘制到设备上,双缓冲绘图是将图形绘制到内存的一张图片上,等所有的绘图完成后再将整幅图片显示在设备上(个人的理解可能 不太准确)。所以这里我们可以将图片设为成员变量。各绘图函数都在该图片上绘图。并且在OnDraw 函数里显示这幅图片,这样就可以在页面切换回来的时候显示以前画的图了。

代码如下:

文件DrawShapeCtrl.h 中:

class CDrawShapeCtrl : public COleControl
{
........
private:
CBitmap m_Bitmap;
//CDC m_dcMem;//切记不能这样定义
BOOL m_bFisrtTime;//第一次加载
BOOL m_bClear; };

DrawShapeCtrl.cpp 中:

CDrawShapeCtrl::CDrawShapeCtrl()
{
InitializeIIDs(&IID_DDrawShape, &IID_DDrawShapeEvents);
// TODO: Initialize your control's instance data here.
m_bFisrtTime = TRUE;
m_bClear = FALSE; }

OnDraw 函数中:

void CDrawShapeCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
if (!pdc)
return; //// TODO: Replace the following code with your own drawing code. CRect rect;
GetClientRect(&rect); CDC dcMem;
dcMem.CreateCompatibleDC(pdc); //first time
if (m_bFisrtTime)
{ m_Bitmap.CreateCompatibleBitmap(pdc,rect.Width(),rect.Height());
dcMem.SelectObject(&m_Bitmap); //填充为白色
dcMem.FillSolidRect(,,rect.Width(),rect.Height(),RGB(,,)); //画坐标轴
CPen pen;
CPen* pOldPen;
pen.CreatePen( PS_DOT, , RGB(,,));
pOldPen = dcMem.SelectObject( &pen ); dcMem.MoveTo(rect.left,rect.Height()/);
dcMem.LineTo(rect.right,rect.Height()/);
dcMem.MoveTo(rect.Width()/,rect.top);
dcMem.LineTo(rect.Width()/,rect.bottom); dcMem.SelectObject(pOldPen);
pOldPen->DeleteObject(); m_bFisrtTime = FALSE; } dcMem.SelectObject(&m_Bitmap);
if (m_bClear)
{ //填充为白色
dcMem.FillSolidRect(,,rect.Width(),rect.Height(),RGB(,,)); //画坐标轴
CPen pen;
CPen* pOldPen;
pen.CreatePen( PS_DOT, , RGB(,,));
pOldPen = dcMem.SelectObject( &pen ); dcMem.MoveTo(rect.left,rect.Height()/);
dcMem.LineTo(rect.right,rect.Height()/);
dcMem.MoveTo(rect.Width()/,rect.top);
dcMem.LineTo(rect.Width()/,rect.bottom); dcMem.SelectObject(pOldPen);
pOldPen->DeleteObject(); m_bClear = FALSE;
} //显示
pdc->BitBlt(,,rect.Width(),rect.Height(),&dcMem,,,SRCCOPY);
dcMem.DeleteDC(); }

画线的函数:

//Lstype--penstyle 线型 Lwidth --线宽度    color--颜色
void CDrawShapeCtrl::Line(LONG x1, LONG y1, LONG x2, LONG y2,LONG Lstyle,LONG Lwidth,OLE_COLOR color)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState()); // TODO: Add your dispatch handler code here CDC *pdc = GetDC(); CRect rcClient;
GetClientRect(rcClient);
CDC memDC;
memDC.CreateCompatibleDC(pdc);
memDC.SelectObject(&m_Bitmap); // Change map mode, positive x right, positive y up.
int nOldMode = memDC.SaveDC();
memDC.SetMapMode(MM_ISOTROPIC);
memDC.SetViewportExt(, );
memDC.SetWindowExt(, -);
memDC.SetViewportOrg(rcClient.Width() / , rcClient.Height()/); //设置画笔线型 宽度 颜色
LOGBRUSH logBrush;
logBrush.lbStyle = BS_SOLID;
logBrush.lbColor = color;
if (Lstyle<||Lstyle>)
{
return;
}
CPen Pen(Lstyle|PS_GEOMETRIC|PS_ENDCAP_ROUND, Lwidth,&logBrush);
memDC.SelectObject(&Pen); //画线
memDC.MoveTo(x1,y1);
memDC.LineTo(x2,y2); // We must restore mapping mode before copy bitmap to client context.
memDC.RestoreDC(nOldMode); // Copy double buffer bitmap to client context.
pdc->BitBlt(, , rcClient.Width(), rcClient.Height(), &memDC, , , SRCCOPY); ReleaseDC(pdc);
memDC.DeleteDC();
}

清空控件内的图形:

void CDrawShapeCtrl::Clear(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState()); // TODO: Add your dispatch handler code here
m_bClear = TRUE; Invalidate(TRUE);
}

在使用的过程当中发现,CDC 不能定义为全局的,必须定义为局部变量,用完随即释放。否则第一次能画出图形,第二次调用的时候什么也画不出来。原因参考

VC CDC类的使用 详解

VC 绘图,使用双缓冲技术实现

https://wenku.baidu.com/view/2c6aaf1ba8114431b90dd862.html

参考:

https://blog.csdn.net/imletterh/article/details/46372753

VC使用双缓冲制作绘图控件的更多相关文章

  1. VC使用双缓冲避免绘图闪烁的正确使用方法【转】

    使用内存DC绘图,然后实现双缓冲,避免绘图闪烁,这个小技术简单但很有效.但是仍然有很多人说使用了双缓冲,图片却仍然有闪烁,分析了几个这样的例子,发现 其实不是双缓冲的技术问题,而是使用者没有正确理解和 ...

  2. VC GDI双缓冲机制绘图防屏幕闪烁实现步骤

    在OnDraw(CDC* pDC) 中添加如下代码 CDC MemDC; //首先定义一个显示设备对象 CBitmap MemBitmap;//定义一个位图对象 //随后建立与屏幕显示兼容的内存显示设 ...

  3. 怎样在VS2013/MFC中使用TeeChart绘图控件

    TeeChart作为一款强大好用的绘图控件,通过它可以绘制出各式各样的图表,包括2D的,还有3D的,绘制的图表美观实用,这里主要讲述如何在VS2013/MFC中使用TeeChart控件,顺便说一下在V ...

  4. PaintView 绘图控件解析

    博客地址:博客园,版权所有,转载须联系作者. GitHub地址:JustWeTools 最近做了个绘图的控件,实现了一些有趣的功能. 先上效果图: PaintView画图工具: 1.可直接使用设定按钮 ...

  5. WPF--Blend制作Button控件模板

    博客园新人,WPF初学者.不涉及理论知识,直接进入操作. 记录一下使用Blend制作Button控件模板过程中,学到Blend几个知识点: 1.渐变画笔编辑器的Alpha选项可以调控件的透明度.即下图 ...

  6. qt超强精美绘图控件 - QCustomPlot一览 及 安装使用教程

    1.概述 QCustomPlot 是一个超强超小巧的qt绘图类,非常漂亮,非常易用,只需要加入一个qcustomplot.h和qcustomplot.cpp文件即可使用,远比qwt方便和漂亮,可以自己 ...

  7. VC/MFC 当鼠标移到控件上时显示提示信息

    VC/MFC 当鼠标移到控件上时显示提示信息 ToolTip是Win32中一个通用控件,MFC中为其生成了一个类CToolTipCtrl,总的说来其使用方法是较简单的,下面讲一下它的一般用法和高级用法 ...

  8. TeeChart绘图控件 - 之三 - 提高绘图的效率 .

    TeeChart是个很强大的控件,其绘图能力之强,其他控件难以比拟,但是有个问题就是他的绘图速度,其实TeeChart绘图速度还是很快的,只是大家一直都没正确运用其功能所以导致绘图速度慢的假象. 下面 ...

  9. VS2010 使用TeeChart绘图控件 - 之二 - 绘制图形(折线图,柱状图)

    1.前期准备 具体可见VS2010 使用TeeChart绘图控件 - 之一 控件和类的导入 1. 1 添加TeeChart控件,给控件添加变量m_TeeChart 添加TeeChart控件,右击控件, ...

随机推荐

  1. sqlserver2008简介

    sql 数据库简介 应该掌握的部分: 1.  数据库的基本概念 2.  数据库模型的基本概念 3.  实体联系模型的基本概念 4.  关系模型的基本概念和性质 5.  数据库优化理论 6.  掌握创建 ...

  2. 思科模拟器-使用vlan划分子网

    此博客为初始化版本,未经完善,后续我再整理一下 小技巧:有时候我们不小心执行了一条错误命令,可以尝试使用在该命令前加一个no进行撤销 首先说一下网络设备的选择 在该实验中我主要用到一台三层交换机(思科 ...

  3. java8_api_io

    IO-1    i/o的概念    File类详解        java.io.File    java.io.FileFilter接口        只有一个方法        这是一个函数式接口 ...

  4. linux 中 && 及|| 判断原理

    [root@linuxprobe ~]# [ $USER = root ] && echo "root" || echo "user"root[ ...

  5. 7_CentOS下安装和卸载AdobeReader

    曾经最喜欢Fedora 版本的Linux,但是因为现在Fedora的界面实在太花里胡哨了,所以最近开始捣鼓CenOS,本来 RedHat的EL版本也是一个不错的选择,最后想想还是用社区版的. 话说Ce ...

  6. .NET Windows服务开发流程

    前段时间做一个数据迁移项目,刚开始用B/S架构做的项目,但B/S要寄存在IIs中,而IIs又不稳定因素,如果重启IIs就要打开页面才能运行项目.有不便之处,就改用Windows服务实现.这篇就总结下, ...

  7. 2016310Exp5 MSF基础应用

    1. 实践目标 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 1.1一个主动攻击实践,如ms08_067; (1分) 1.2 一个针对浏览器的攻击, ...

  8. IOC注入框架——Unity中Web.Config文件的配置与调用

    Unity 应用程序块可以从 XML 配置文件中读取配置信息.配置文件可以是 Windows Forms 应用程序的 App.config 或者 ASP.NET 应用程序的 Web.config.当然 ...

  9. SfMLearner 记录

    2019年3月2日09:29:54 正在看SfMLearner的pytorch源码,意识到无监督的深度估计最重要的是利用实体的一致性 来建立loss. 对于一个不移动的物体,相机从一个pose到另一个 ...

  10. chrony 时间同步服务器

    这篇文章也不错: https://www.zfl9.com/chrony.html 简介 chrony是网络时间协议(NTP)的多用途实现.它可以使系统时钟与NTP服务器.参考时钟(例如GPS接收器) ...