MFC双缓冲绘图实例
本人之前一直了解双缓冲绘图的基本原理,但是在研究很久之后才大概知道具体的使用过程,本文将详细介绍本人在实际项目中使用双缓冲绘图的案例。
实现功能:主界面显示某张包含人脸的图片,通过dlib detector获取到人脸上的68个关键点,绘制在图片上显示,然后通过鼠标拖动图片上的关键点,调整位置,之后保存。双缓冲主要能够解决拖动关键点时屏幕闪烁的问题,本文主要侧重在双缓冲的实现,其他功能概不介绍。
具体实现:
1.定义全局变量:
CDC dc_mem://内存绘制dc CDC *dc://绘图dc vector<CPoint> face://保存人脸中关键点的坐标 CBitmap bitmap; //内存绘图相关变量 CImage image;
2.在OnInitDialog()函数中初始化绘图dc=GetDC();
3.OnEraseBkgnd()函数直接return true;
添加函数afx_msg BOOL OnEraseBkgnd(CDC* pDC);
添加消息ON_WM_ERASEBKGND();
这一步很关键!!!
4.在OnPaint()中调用DrawOnBuffer()绘图
void CEditLmDlg::DrawOnBuffer()
{
CRgn rgn;
rgn.CreateRectRgn(0, 0, image_width, image_height);
dc->SelectClipRgn(&rgn); dc_mem.CreateCompatibleDC(dc);
bitmap.CreateCompatibleBitmap(dc, edit_rect.Width(), edit_rect.Height());
CBitmap *pOldBit = dc_mem.SelectObject(&bitmap);
dc_mem.FillSolidRect(edit_rect, dc->GetBkColor()); dc_mem.SetStretchBltMode(HALFTONE);
CRect rect(0, 0, image_width, image_height);
image.Draw(dc_mem.m_hDC, rect); dc->BitBlt(0, 0, edit_rect.Width(), edit_rect.Height(), &dc_mem, 0, 0,SRCCOPY); /**将所有的点绘制到dc_mem上*/代码略 dc->SelectClipRgn(NULL);
dc_mem.DeleteDC();
bitmap.DeleteObject();
}
函数中CreateRectRgn函数设置裁剪区可以保证刷新时只刷新图片的部分,不刷新图片外的其他控件,这样其他控件就不会出现闪烁的情况,另外函数结束时要将裁剪区设置为空。
5.至于拖动关键点的操作需要调用以下三个函数,以及声明对应的三个消息即可,在OnLButtonUp,OnMouseMove中将变化后的点的坐标更新到face中,并调用Invalidate()即可。
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point); ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
综上,双缓冲绘图的关键是怎么把所有的绘图操作放到一个绘图函数中,该过程可能需要很多的全局变量来保存绘图相关数据。
MFC双缓冲绘图实例的更多相关文章
- MFC双缓冲绘图(2015.09.24)
问题引入: 最近在尝试编写贪吃蛇游戏时遇到这么一个问题:当系统以较快频率向窗口发送WM_PAINT消息时,调用OnPaint()函数在窗口中绘制图形就会发生闪烁现象. 问题分析: 当我们把绘图过程放在 ...
- mfc双缓冲绘图
1.要求 在界面加载本地图片并显示,每过100ms改变一张图片显示 2.现象 通过定时器控制CImage,Load,Draw,Destroy,会非常的卡顿.因为Load图片时,会是非常大的数据[所有C ...
- MFC双缓冲解决图象闪烁[转]
转载网上找到的一篇双缓冲的文章,很好用.http://www.cnblogs.com/piggger/archive/2009/05/02/1447917.html__________________ ...
- 【MFC】MFC绘制动态曲线,用双缓冲绘图技术防闪烁
摘自:http://zhy1987819.blog.163.com/blog/static/841427882011614103454335/ MFC绘制动态曲线,用双缓冲绘图技术防闪烁 2011 ...
- C#-gdi绘图,双缓冲绘图,Paint事件的触发
一. 画面闪烁问题与双缓冲技术 1.1 导致画面闪烁的关键原因分析: 1 绘制窗口由于大小位置状态改变进行重绘操作时 绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面 ...
- 陈灯WGF双缓冲绘图框架
“木丸子童屋”,专售各类儿童玩具,价格优惠,请大家多多支持:http://shop65552598.taobao.com/ WGF(windows graphic foundation)为window ...
- [Qt2D绘图]-06QPainter的复合模式&&双缓冲绘图&&绘图中的其他问题
本篇读书笔记主要记录QPainter的复合模式&&双缓冲绘图&&绘图中的其他问题 大纲: 复合模式 双缓冲绘图 绘图中的其他问题 ...
- 双缓冲绘图和窗口控件的绘制——ATL ActiveX 窗口控件生成向导绘制代码OnDraw的一个错误 .
双缓冲绘图和窗口控件的绘制 ---ATL ActiveX 窗口控件生成向导绘制代码OnDraw的一个错误 cheungmine 我们通常使用ATL COM组件,生成一个带窗口的ActiveX控件,然后 ...
- 简单的 "双缓冲" 绘图的例子(研究一下)
所谓双缓冲就是先画到内存画布(如: TBitmap), 然后再转帖到目的地. 譬如下面小程序: procedure TForm1.FormCreate(Sender: TObject); begin ...
随机推荐
- 泛函编程(6)-数据结构-List基础
List是一种最普通的泛函数据结构,比较直观,有良好的示范基础.List就像一个管子,里面可以装载一长条任何类型的东西.如需要对管子里的东西进行处理,则必须在管子内按直线顺序一个一个的来,这符合泛函编 ...
- 【poj 2185】Milking Grid(字符串--KMP+问题分解)
题意:给定一个由字符组成的矩阵,求出它的面积最小的覆盖矩阵.(感觉应该是可重叠的......* (・ω・)っ) 解法:KMP.行列互不影响,可以问题分解.先求出每一行的最小重复串,利用kmp中的nex ...
- mybatis/callablestatement调用存储过程mysql connector产生不必要的元数据查询
INFO | jvm 1 | 2016/08/25 15:17:01 | 16-08-25 15:17:01 DEBUG pool-1-thread-371dao.ITaskDao.callProce ...
- Android笔记——Android中数据的存储方式(二)
我们在实际开发中,有的时候需要储存或者备份比较复杂的数据.这些数据的特点是,内容多.结构大,比如短信备份等.我们知道SharedPreferences和Files(文本文件)储存这种数据会非常的没有效 ...
- 调试CRM JS开发
CRM 2013 的表单是一个IFrame,如果使用jquey来控制表单的话调试起来比较麻烦,如果直接使用浏览器(firefox)来开发和验证脚本可能会事半功倍. 首页列表页主窗体:var table ...
- Installing FIM 2010 R2 SP1 Portal on SharePoint Foundation 2013
http://www.fimspecialist.com/fim-portal/installing-fim-2010-r2-sp1-portal-on-sharepoint-foundation-2 ...
- Configure SSL for SharePoint 2013
http://blogs.msdn.com/b/fabdulwahab/archive/2013/01/21/configure-ssl-for-sharepoint-2013.aspx In thi ...
- Android 优秀的开源框架整理
第一部分:系统架构 thinkAndroid https://github.com/white-cat/ThinkAndroid ThinkAndroid是一个免费的开源的.简易的.遵循Apache2 ...
- Android-Application
1:Application是什么? Application和Activity,Service一样,是android框架的一个系统组件,当android程序启动时系统会创建一个 application对 ...
- 关于NSDate和NSDateFormatter的几个常用方法
/** * NSDate常见类方法 */ // 获得当前时间 NSDate *date1 = [NSDate date]; // 类方法 // NSDate *date1 = [[NSDate ...