在MFC中绘制比较复杂图形,通常采用双缓冲技术来绘图,的确可以大大加快绘制速度和减少闪烁,但是有些情况也不尽然。

我最近遇到了一个问题,采用的也是双缓冲来加快绘图,但是绘制效果还是不尽人意。A对象里大约有几百个可以绘画的对象,每个对象都没有填充背景,他们的背景是另一对象B。A和B在一个窗口中可能有N个,绘画时,先绘制B然后在绘制A,只有2、3个A对象的时候,绘画已经比较慢了,DEBUG下可以明显感觉到延迟,原因是我可能只改变了对象B或一个A对象,但是需要把所有的对象重新绘画一边,效率非常低,即使是用上双缓冲也不行,PS大家都用过,它里面有一个叫做透明层的概念,在透明层上画任何东西不影响下面的层,那么我们能不能将A对象绘画在一个"透明层"1上,将B对象绘画在另一"透明层"2上。改变A对象时只需要重新在"透明层"1重新绘制A对象,而"透明层"2不需要重新绘制,最后先画透明层1然后再画透明层2,这样效率就可以大大提高了。

问题的关键之处是创建一个透明位图,然后在这个透明的位图上绘制图形。

注意:演示代码使用了GDI+,因为GDI没有使用ARGB,不会改写Alpha的值,即使画了也显示不出来。

1、首先写一个CPngMem类。

  1. class CPngMemDC
  2. {
  3. public:
  4. CPngMemDC() : m_hBmp(NULL)
  5. {
  6. }
  7. ~CPngMemDC()
  8. {
  9. if (m_hBmp)
  10. ::DeleteObject(m_hBmp);
  11. }
  12.  
  13. //创建内存DC
  14. void CreateMemDC(CDC *pDC)
  15. {
  16. ASSERT(pDC);
  17.  
  18. if (m_MemDC.GetSafeHdc())
  19. m_MemDC.DeleteDC();
  20. m_MemDC.CreateCompatibleDC(pDC);
  21. }
  22.  
  23. //创建位图,并将位图选进内存DC
  24. void CreateBitmap(int nWidth, int nHeight)
  25. {
  26. BITMAPINFO bi;
  27. bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  28. bi.bmiHeader.biBitCount = 32;
  29. bi.bmiHeader.biHeight = nHeight;
  30. bi.bmiHeader.biWidth = nWidth;
  31. bi.bmiHeader.biPlanes = 1;
  32. bi.bmiHeader.biCompression = BI_RGB;
  33. bi.bmiHeader.biXPelsPerMeter = 0;
  34. bi.bmiHeader.biYPelsPerMeter = 0;
  35. bi.bmiHeader.biClrUsed = 0;
  36. bi.bmiHeader.biSizeImage = 0;
  37. bi.bmiHeader.biSizeImage = nWidth * nHeight * bi.bmiHeader.biBitCount / 8;
  38.  
  39. if (m_hBmp)
  40. ::DeleteObject(m_hBmp);
  41. m_hBmp = ::CreateDIBSection(m_MemDC, &bi, 0, NULL, 0, 0);//创建32位位图
  42.  
  43. m_MemDC.SelectObject(m_hBmp);
  44.  
  45. m_nWidth = nWidth;
  46. m_nHeight = nHeight;
  47. }
  48.  
  49. void Draw(CDC *pDC)
  50. {
  51. BLENDFUNCTION bf;
  52. bf.AlphaFormat = AC_SRC_ALPHA;
  53. bf.BlendFlags = 0;
  54. bf.BlendOp = AC_SRC_OVER;
  55. bf.SourceConstantAlpha = 255;
  56.  
  57. BOOL bRet = pDC->AlphaBlend(0, 0, m_nWidth, m_nHeight,
  58. &m_MemDC, 0, 0, m_nWidth, m_nHeight, bf);
  59. VERIFY(bRet);
  60. }
  61.  
  62. operator HDC()//重载HDC类型转换
  63. {
  64. return m_MemDC.GetSafeHdc();
  65. }
  66.  
  67. private:
  68. CDC m_MemDC;
  69. HBITMAP m_hBmp;
  70.  
  71. int m_nWidth;
  72. int m_nHeight;
  73. };

1、在对话框类中添加两个成员变量:

  1. private:
  2. CPngMemDC m_pngMem1;
  3. CPngMemDC m_pngMen2;

2、在OnInitDialog()函数中创建内存DC和位图:

  1. CClientDC dc(this);
  2. CRect rcClient;
  3. GetClientRect(rcClient);
  4.  
  5. m_pngMem1.CreateMemDC(&dc);
  6. m_pngMem1.CreateBitmap(rcClient.Width(), rcClient.Height());
  7.  
  8. m_pngMen2.CreateMemDC(&dc);
  9. m_pngMen2.CreateBitmap(rcClient.Width(), rcClient.Height());

3、添加OnBnClickedOk()按钮响应函数:

  1. void CDlg::OnBnClickedOk()
  2. {
  3. Graphics g1(m_pngMem1);
  4. Pen pen1(Color(255, 255, 0, 0), 5);//红色
  5. g1.DrawLine(&pen1, Point(100, 0), Point(100, 300));
  6.  
  7. Graphics g2(m_pngMen2);
  8. Pen pen2(Color(0, 255, 0), 5);//绿色
  9. g2.DrawLine(&pen2, Point(0, 150), Point(300, 150));
  10.  
  11. CClientDC dc(this);
  12.  
  13. m_pngMem1.Draw(&dc);
  14. m_pngMen2.Draw(&dc);
  15. }

最后显示结果如下:

MFC 透明内存DC的更多相关文章

  1. 关于内存DC

    使用CreateCompatibleDC 创建了内存DC之后,要再调用SelectObject选择一张位图放入此DC,然后才可以使用此DC进行绘制,之后绘制的数据会保存在内存中, 详细说明看后文. 在 ...

  2. MFC多线程内存泄漏问题&解决方法

    在用visual studio进行界面编程时(如MFC),前台UI我们能够通过MFC的消息循环机制实现.而对于后台的数据处理.我们可能会用到多线程来处理. 那么对于大多数人(尤其是我这样的菜鸟),一个 ...

  3. mfc 动态分配内存

     动态内存分配new  为数组动态分配内存  为多维数组分配内存  释放内存delete malloc free  动态内存分配new int * pi; pi= new int ;  为 ...

  4. 使用mfc CHtmlView内存泄露解决方法

    第一步,谷歌有文章说CHtmlView部分api使用BSTR没释放: 解决方法是重写一下接口: CString GetFullName() const; CString GetFullName() c ...

  5. 《MFC游戏开发》笔记三 游戏贴图与透明特效的实现

    本系列文章由七十一雾央编写,转载请注明出处. 313239 作者:七十一雾央 新浪微博:http://weibo.com/1689160943/profile?rightmod=1&wvr=5 ...

  6. MFC 可以设置背景色、字体、字体颜色、透明背景的 Static 静态文本控件

    MFC库里没有符合这个条件的控件,于是我自己写了一个,初步测试有效. 注:可以设置透明背景,但还不能做到透明度设置(如50%透明度) 如果设置了背景色,就不保留透明背景 默认背景色是透明的 [cpp] ...

  7. 如何将内存中的位图数据绘制在DC上

    假如你定义了一个位图类,里面包含位图头,位图信息头,调色板,位图数据.然后你按照位图的格式将位图文件读入你的类中,现在你知道了位图的全部信息了.主要信息包含在位图信息头里面,数据则在位图数据缓冲里面. ...

  8. 《MFC游戏开发》笔记六 图像双缓冲技术:实现一个流畅的动画

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/9334121 作者:七十一雾央 新浪微博:http:/ ...

  9. 【Visual C++】游戏编程学习笔记之一:五毛钱特效之透明和半透明处理

    本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44163799 作者:ZeeCod ...

随机推荐

  1. 图的存储结构:邻接矩阵(邻接表)&链式前向星

    [概念]疏松图&稠密图: 疏松图指,点连接的边不多的图,反之(点连接的边多)则为稠密图. Tips:邻接矩阵与邻接表相比,疏松图多用邻接表,稠密图多用邻接矩阵. 邻接矩阵: 开一个二维数组gr ...

  2. C#读取和写入文件

    一.读取文件 如果你要读取的文件内容不是很多, 可以使用 File.ReadAllText(FilePath) 或指定编码方式 File.ReadAllText(FilePath, Encoding) ...

  3. memo用法总结

    添加 mmo1.Lines.add('新加的一行');//追加一行文字 mmo1.Lines.Insert(1,'新插入一行');//在指定位置插入一行 删除 mmo1.Lines.Delete(1) ...

  4. cmd alias 自定义命令

    简短步骤:1.关闭所有在运行的CMD窗口2.创建文件C:\cmd-alias.bat,包含以下内容:[python] view plain copydoskey sayhello=echo Hello ...

  5. apicloud 初学

    html5:在创建html时为了防止页面缩放等不兼容效果,要创建个viewport <meta name="viewport" content="maximum-s ...

  6. Sublime Text学习笔记

    1.快捷键(Key Bindings)   Preferences -> Key Bindings ->Default   会打开一个配置文件,里面全是配置信息 2.代码片段(Snippe ...

  7. CCNET+MSBuild+SVN实时构建的优化总结

    本文不是介绍如何使用CCNET+MSBuild+SVN构建自动编译系统,相关的内容可以从很多地方获取,可以再园子里搜一下. 随着我们的SVN库日益壮大,容量达到10G,几十G 甚至更大时,我们发现自动 ...

  8. Strusts2--课程笔记4

    类型转换器: Struts2默认情况下可以将表单中输入的文本数据转换为相应的基本数据类型.这个功能的实现,主要是由于Struts2内置了类型转换器.这些转换器在struts-default.xml中可 ...

  9. web.config中httpModules和Modules的区别

    最近用到了mvc的 Modules管道时,发现web.config中有两个modules 1.system.web节点下的httpModules 2.system.webServer节点下的modul ...

  10. Logger日志管理工具类

    import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import j ...