MFC 透明内存DC
在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类。
class CPngMemDC
{
public:
CPngMemDC() : m_hBmp(NULL)
{
}
~CPngMemDC()
{
if (m_hBmp)
::DeleteObject(m_hBmp);
} //创建内存DC
void CreateMemDC(CDC *pDC)
{
ASSERT(pDC); if (m_MemDC.GetSafeHdc())
m_MemDC.DeleteDC();
m_MemDC.CreateCompatibleDC(pDC);
} //创建位图,并将位图选进内存DC
void CreateBitmap(int nWidth, int nHeight)
{
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biHeight = nHeight;
bi.bmiHeader.biWidth = nWidth;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biXPelsPerMeter = 0;
bi.bmiHeader.biYPelsPerMeter = 0;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biSizeImage = 0;
bi.bmiHeader.biSizeImage = nWidth * nHeight * bi.bmiHeader.biBitCount / 8; if (m_hBmp)
::DeleteObject(m_hBmp);
m_hBmp = ::CreateDIBSection(m_MemDC, &bi, 0, NULL, 0, 0);//创建32位位图 m_MemDC.SelectObject(m_hBmp); m_nWidth = nWidth;
m_nHeight = nHeight;
} void Draw(CDC *pDC)
{
BLENDFUNCTION bf;
bf.AlphaFormat = AC_SRC_ALPHA;
bf.BlendFlags = 0;
bf.BlendOp = AC_SRC_OVER;
bf.SourceConstantAlpha = 255; BOOL bRet = pDC->AlphaBlend(0, 0, m_nWidth, m_nHeight,
&m_MemDC, 0, 0, m_nWidth, m_nHeight, bf);
VERIFY(bRet);
} operator HDC()//重载HDC类型转换
{
return m_MemDC.GetSafeHdc();
} private:
CDC m_MemDC;
HBITMAP m_hBmp; int m_nWidth;
int m_nHeight;
};
1、在对话框类中添加两个成员变量:
private:
CPngMemDC m_pngMem1;
CPngMemDC m_pngMen2;
2、在OnInitDialog()函数中创建内存DC和位图:
CClientDC dc(this);
CRect rcClient;
GetClientRect(rcClient); m_pngMem1.CreateMemDC(&dc);
m_pngMem1.CreateBitmap(rcClient.Width(), rcClient.Height()); m_pngMen2.CreateMemDC(&dc);
m_pngMen2.CreateBitmap(rcClient.Width(), rcClient.Height());
3、添加OnBnClickedOk()按钮响应函数:
void CDlg::OnBnClickedOk()
{
Graphics g1(m_pngMem1);
Pen pen1(Color(255, 255, 0, 0), 5);//红色
g1.DrawLine(&pen1, Point(100, 0), Point(100, 300)); Graphics g2(m_pngMen2);
Pen pen2(Color(0, 255, 0), 5);//绿色
g2.DrawLine(&pen2, Point(0, 150), Point(300, 150)); CClientDC dc(this); m_pngMem1.Draw(&dc);
m_pngMen2.Draw(&dc);
}
最后显示结果如下:
MFC 透明内存DC的更多相关文章
- 关于内存DC
使用CreateCompatibleDC 创建了内存DC之后,要再调用SelectObject选择一张位图放入此DC,然后才可以使用此DC进行绘制,之后绘制的数据会保存在内存中, 详细说明看后文. 在 ...
- MFC多线程内存泄漏问题&解决方法
在用visual studio进行界面编程时(如MFC),前台UI我们能够通过MFC的消息循环机制实现.而对于后台的数据处理.我们可能会用到多线程来处理. 那么对于大多数人(尤其是我这样的菜鸟),一个 ...
- mfc 动态分配内存
动态内存分配new 为数组动态分配内存 为多维数组分配内存 释放内存delete malloc free 动态内存分配new int * pi; pi= new int ; 为 ...
- 使用mfc CHtmlView内存泄露解决方法
第一步,谷歌有文章说CHtmlView部分api使用BSTR没释放: 解决方法是重写一下接口: CString GetFullName() const; CString GetFullName() c ...
- 《MFC游戏开发》笔记三 游戏贴图与透明特效的实现
本系列文章由七十一雾央编写,转载请注明出处. 313239 作者:七十一雾央 新浪微博:http://weibo.com/1689160943/profile?rightmod=1&wvr=5 ...
- MFC 可以设置背景色、字体、字体颜色、透明背景的 Static 静态文本控件
MFC库里没有符合这个条件的控件,于是我自己写了一个,初步测试有效. 注:可以设置透明背景,但还不能做到透明度设置(如50%透明度) 如果设置了背景色,就不保留透明背景 默认背景色是透明的 [cpp] ...
- 如何将内存中的位图数据绘制在DC上
假如你定义了一个位图类,里面包含位图头,位图信息头,调色板,位图数据.然后你按照位图的格式将位图文件读入你的类中,现在你知道了位图的全部信息了.主要信息包含在位图信息头里面,数据则在位图数据缓冲里面. ...
- 《MFC游戏开发》笔记六 图像双缓冲技术:实现一个流畅的动画
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9334121 作者:七十一雾央 新浪微博:http:/ ...
- 【Visual C++】游戏编程学习笔记之一:五毛钱特效之透明和半透明处理
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44163799 作者:ZeeCod ...
随机推荐
- 回车事件jquery
有时候,操作按钮需要回车键 直接上代码: //回车事件document.onkeydown = function (e) { var ev = document.all ? window.event ...
- VLAN学习
IEEE于1999年颁布了标准化VLAN实现方案的 IEEE 802.1Q 协议标准草案,对带有VLAN标识的报文结构进行了统一规定. 传统的以太网数据帧在目的MAC和源MAC地址之后封装的是上层协议 ...
- shell脚本学习(五)
1.统计文件的行数.单词数.字符数 1)行数: wc -l file cat file | wc -l 2)单词数 wc -w file cat file | wc -w 3)统计字符数 wc -c ...
- js添加div
有这样一段div布局 <div class="clearfix"> <p class="left c"> <s ...
- C# List 扩展排序
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Comm ...
- C语言_用if```else语句解决奖金发放问题
#include<stdio.h> #include<stdlib.h> /*企业发放的奖金根据利润提成,发放规则如下: 利润(I)低于或等于10万元时,奖金可提10%: 利润 ...
- keybd_event 对应表
Option Explicit Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bSc ...
- YII 常用路径总结
Yii framework已经定义的命名空间常量 system: 指向Yii框架目录; YII\framework zii: 指向zii library 目录; YII\framework\zii ...
- Java中String转换Double类型 Java小数点后留两位
Java中String转换Double类型 double num1 = 0.0; String qq = "19.987"; num1 = Double.valueOf(qq.to ...
- JavaScript高级程序设计:第二十一章
第二十一章 Ajax与Comet 一.XMLHttpRequest对象 1.XHT的用法 在使用XHR对象时,要调用的第一个方法时open( ),它接受3个参数:要发送的请求的类型.请求的URL和表示 ...