MFC---定时器和双缓冲机制绘制旋转的金刚石图案
双缓冲原理
MFC中绘制动画的基本思路是在固定时间间隔内绘制图像,然后擦除旧图像再绘制新图像,这样连续 起来就在人类的视觉上形成动画。为了实现这种“绘制-擦除-再绘制”的思路,较老的一种方法是在 OnDraw函数中绘图,然后利用InValidate函数来清空屏幕,然后再绘制新图。因为绘制新旧两幅图像之 间必定需要一定的计算和绘制时间,导致一个后果就是图像闪烁的很厉害。
为了避免闪烁,借助于双缓冲的思想,我们可以在显示一幅图像的同时,在后台计算一幅新图像,并 将新图像保存为一个完整的位图。当时间间隔到期后,一次性将新图像位图读入并显示出来即可。这样 将大大节省计算和绘制的时间。实际运行中,人类的视觉基本感知不到任何闪烁。定时器
(1) 创建定时器。创建定时器使用SetTimer函数。
SetTimer函数的原型
UINT_PTRSetTimer(
HWND hWnd,//窗口句柄
UINT nIDEvent,//定时器ID,多个定时器时,可以通过该ID判断是哪个定时器
UINT nElapse,//时间间隔,单位为毫秒
TIMERPROC lpTimerFunc//回调函数
);
例:
SetTimer(m_hWnd,1,1000,NULL);//一个1秒触发一次的定时器
在MFC程序中SetTimer被封装在CWnd类中,调用就不用指定窗口句柄了
于是SetTimer函数的原型变为:
UINTSetTimer(UINT nIDEvent,UINT nElapse,void(CALLBACKEXPORT *lpfnTimer)(HWND,UINT,YINT,DWORD))
当使用SetTimer函数的时候,就会生成一个定时器,函数中nIDEvent指的是定时器的标识,也就是名字。nElapse指的是时间间隔,也就是每隔多长时间触发一次事件。第三个参数是一个回调函数,在这个函数里,放入你想要做的事情的代码,你可以将它设定为NULL,也就是使用系统默认的回调函数,系统默认的是OnTimer函数。这个函数怎么生成的呢?你需要在需要计时器的类的生成OnTimer函数:在ClassWizard里,选择需要计时器的类,添加WM_TIMER消息映射,就自动生成OnTimer函数了。然后在函数里添加代码,让代码实现功能。每隔一段时间就会自动执行一次。
(2) 处理定时器信号。MFC在OnTimer函数中处理定时器信号。OnTimer函数具有一个参数,是捕捉到的定 时器编号。
(3) 销毁定时器。定时器也会占用一定的系统资源,所以必须及时销毁不用的定时器,否则会影响系统运行 效率。MFC中使用KillTimer函数销毁定时器,该函数参数就是待销毁的定时器编号。
函数原型:
KillTimer(
hWnd: HWND; //与定时器相关联的窗口句柄
nIDEvent: UINT //定时器标识符
):
参数:
hWnd:与定时器相关联的窗口句柄
nIDEvent: SetTimer的第二个参数。
说明:
销毁以前调用SetTimer创建的用nIDEvent标识的定时器事件。不能将此定时器有关的未处理的WM_TIMER消息都从消息队列中清除。部分代码:
//绘制旋转的金刚石图案,以下给出主要的代码。//新建一个单文档Test,在View类中添加绘图函数DIAmond();添加成员变量:Theta=2*PI/n; //θ为等分角Alpha=PI/2-Theta; //α为起始角,用于调整图案起始方位n=10; //为等分点个数r=200; //为圆的半径CPoint p[60]; //存储等分点坐标flag = 1; //初始为旋转void CTestView::DIAmond() { CDC *pDC=GetDC(); //定义设备上下文指针 CRect rect; //定义矩形对象 GetClientRect(&rect); //获得客户区矩形的大小 CDC dcMem; //用于缓冲作图的内存DC CBitmap bmp; //内存中承载临时图象的位图 dcMem.CreateCompatibleDC(pDC); //依附窗口DC创建兼容内存DC bmp.CreateCompatibleBitmap(&dcMem,rect.Width(),rect.Height());//创建兼容位图 dcMem.SelectObject(&bmp); //将位图选择进内存DC CPen NewPen,*pOldPen; //定义画笔 NewPen.CreatePen(PS_SOLID,1,RGB(255,255,255)); //创建无色画笔 pOldPen=dcMem.SelectObject(&NewPen); //将无色画笔选入设备上下文 for(int i=0;i<n;i++) //计算等分点坐标 { p[i].x=r*cos(i*Theta+Alpha) + rect.Width()/2; p[i].y=r*sin(i*Theta+Alpha) + rect.Height()/2; } for(i=0;i<=n-2;i++) //依次连接各等分点 { for(int j=i+1;j<=n-1;j++) { dcMem.MoveTo(Round(p[i].x),Round(p[i].y)); dcMem.LineTo(Round(p[j].x),Round(p[j].y)); } } pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY); //将内存DC上的图象拷贝到前台 dcMem.SelectObject(pOldPen); //恢复设备上下文中的原画笔 NewPen.DeleteObject(); //删除已成自由状态的蓝色画笔 ReleaseDC(pDC); //释放设备上下文指针 dcMem.DeleteDC(); } // 设置菜单项,添加菜单响应函数void CTestView::OnDrawpic() //控制旋转和暂定{<span style="white-space:pre"> </span>if(flag){flag= 0;SetTimer(1,100,NULL); //设置定时器}else{flag = 1;KillTimer(1); //销毁定时器}}// 添加消息函数OnTimer() void CTestView::OnTimer(UINT nIDEvent) //处理定时器函数{Alpha += PI/12; //起始角度,变式的控制旋转,可以更改定时器的值控制旋转的速度DIAmond(); CView::OnTimer(nIDEvent); }// 在DiamondView.cpp文件开头需要包含以下头文件#include"math.h" //包含数学头文件#define PI 3.1415926 //PI的宏定义#define Round(f) int(floor(f+0.5)) //四舍五入宏定义
MFC---定时器和双缓冲机制绘制旋转的金刚石图案相关推荐
- 关于Surface的底层双缓冲机制学习
双缓冲机制 问题的由来 CPU访问内存的速度要远远快于访问屏幕的速度.如果需要绘制大量复杂的图像时,每次都一个个从内存中读取图形然后绘制到屏幕就会造成多次地访问屏幕,从而导致效率很低.这就跟CPU和内 ...
- android缓冲机制,Android自定义View之双缓冲机制和SurfaceView
Android自定义View系列 双缓冲机制 问题的由来 CPU访问内存的速度要远远快于访问屏幕的速度.如果需要绘制大量复杂的图像时,每次都一个个从内存中读取图形然后绘制到屏幕就会造成多次地访问屏幕, ...
- QT5开发及实例学习之十七Qt5双缓冲机制
文章目录 一.原理与设计 二.绘图区的实现 三.主窗口的实现 一.原理与设计 所谓双缓冲机制,是指在绘制控件时,首先将要绘制的内容绘制在一个图片中,再将图片一次性地绘制到控件上.在早期的 Qt 版 ...
- Android SurfaceView的双缓冲机制,引起的闪屏问题
SurfaceView相关目录 SurfaceView要点 SurfaceView拥有独立的Surface(绘图表面) SurfaceView是用Zorder排序的,他默认在宿主Window的后面,S ...
- 今儿新学会一个写日志技能:双缓冲机制
摘要:通过交换指针的方式实现两个缓冲区的功能互换,十分巧妙,令人称赞. 本文分享自华为云社区<奇妙的双缓冲机制写日志(Java实现)>,作者: 洛叶飘 . 写日志面临的问题 写日志在Web ...
- Linux-FrameBuffer双缓冲机制显示图像
1. 液晶屏的基本概念 像素: 屏幕上显示颜色的最小单位,英文叫 pixel.注意,位图(如jpg.bmp等格式的常见图片)也是由一个个的像素点构成的,跟屏幕的像素点的概念一样.原理上讲,将一张位图显 ...
- EGE基础入门篇(九):双缓冲与手动渲染
EGE专栏:EGE专栏 上一篇:EGE基础入门篇(八):清屏与重绘 下一篇: 文章目录 一.双缓冲机制 1. 单缓冲绘图 1.1 单缓冲绘图的缺点 1.2 系统读取帧缓冲 2. 双缓冲绘图 2.1 双 ...
- 多线程异步日志系统,高效、强悍的实现方式-双缓冲
作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 目录 文章目录 单片机中常用的环形缓冲区 多线程异步日志:双缓冲机制 双缓冲机制为什么高效 尽可能的降低 Lock 的时 ...
- [转载] MFC绘制动态曲线,用双缓冲绘图技术防闪烁
转载的原文地址 先上效果图 随着时间的推移,曲线向右平移,同时X轴的时间坐标跟着更新. 一.如何绘制动态曲线 所谓动画,都是一帧一帧的图像连续呈现在用户面前形成的.所以如果你掌握了如何绘制静态曲线,那 ...
最新文章
- 367. Valid Perfect Square
- 看到他我一下子就悟了-- Lambda表达式
- e 签宝携手神策数据,数据赋能智能办公产品服务双升级
- 恢复博客更新 --- 逆序单项链表 要求空间复杂度o(1) 时间复杂度o(n)
- angularjs ajax header,angularJs/ajax跨域请求携带cookies
- 从一个实例看javascript几种常用格式的转换
- java afconsole_Java ——基础语法
- es6关于let和const的总结
- Hibernate 缓存的使用
- Spring Boot Mybatis简单使用
- 打造网红内容和资本哪个更重要
- 这行简单的网址可令Chrome立马崩溃
- Oauth协议是否会泄露用户的密码
- 集群中运行Tachyon(译)
- 后台异常 - Content is not allowed in prolog
- centos6 ab性能测试web服务器
- matlab imrotate中心,MATLAB imrotate函数的用法
- 计算机基础西南大学,西南大学计算机基础.docx
- 新加坡区块链ICO公司是如何注册新加坡公司的
- 手把手教你给女朋友编写一个公众号定时推送(java版本)