如何在MFC内实现雪花动画(修正补充篇)

来源:互联网 发布:欣奕除疤淘宝官网 编辑:程序博客网 时间:2024/04/30 01:08

       时隔一年了,在MFC内实现雪花飘动效果的设计的更新也停滞了N久,博文《如何在MFC内实现雪花动画》重点讲解了第二种雪花贴图的方式,原理简单易懂广受好评。最近,有读

者反映,第一种实现雪花贴图的方法因为涉及成员数量多,贴图次数多且过程复杂,让人

眼花缭乱。我也只能说,贴图在程序中作为一种高级的操作,原理有时候是只可意会而不

可言传的,必须在掌握基础知识的前提下,在实践中积累经验并最终掌握方法。

      下面,我结合之前CSDN的友人Conry提到过:“没必要用第二个对话框作为背景填充显示。单纯利用dest内存在的背景数据作为支持即可。”将第二种显示动画背景的方案提出,

并根据个人理解,讲解第一种方案内实现动画的原理。


      较第二种方案,第一种方案有2个好处:
1、背景图片拉伸后可以和动画联合在一起,失真少;
2、其创建了直接的动画背景,并且控件边缘和雪花动画融合得天衣无缝。

      第一种方案创造雪花动画,主要和2个函数有关:Init()和Method1()。其中Init()负责进

行拉伸背景的创建和各个贴图成员的初始化,Method1()负责雪花透空处理和动画效果的

产生,最后,通过OnTimer启动动画,并结合OnPaint() 来刷新显示。

      下边讲解一下Init()的原理,
      原先在博文《如何在MFC内实现雪花动画》中,源程序背景显示是通过创建另一个和主动

画窗体CTSnowDlg大小相同,并置于其后的窗体CBkDlg作为虚拟背景载入的。因为有了方

案1,所以得以使用其内的成员CBitmap dest完美地显示背景和动画,只需要做如下改进

即可:

 

 

 

经过以上代码后,再运行程序,可以看到,在程序初始化后弹出的窗体界面,就直接显示

了雪花背景图,和原先利用双层对话框组合实现雪花动画的背景效果一致,见下图1:

 

初始化流程图如下(未完成):

详细代码注释如下:

 

      代码注释内,有我重点提示的说明语句//********//,读者不妨试试看,就可以了解这些语句的作用了。

      好,明白了初始化的必要步骤后,我们接下来讲解动画原理。Method1()内,不仅实现了

雪花动画,而且还实现了将雪花图片进行透空的处理。


透空流程图如下(未完成):
详细代码注释如下:

      以上流程和方法,同样可以扩展延伸到控件方面和动画雪花相互融合的场合,读者在运行

本程序的时候,一定发现了方案1和方案2中雪花在左上角的皇冠中飘落时候的差别,见下

图2:

      对,这就是Method1()的魅力之二。同理子类化控件,构成类TransparentImage,void TransparentImage::OnPaint()内的代码结构,即其透空原理和void

CTSnowDlg::Method1()一致。
      所不同的是,void CTSnowDlg::Method1()内memDC1作用等同于void

TransparentImage::OnPaint()中的destDC;memDC2的兼并了负责载入Mask图 和 image图的功能,需要多次SelectObject,而void TransparentImage::OnPaint()中,则是区分了蒙版图和image图,分别用不同的DC变量载入,经过一系列复杂的内存贴图处理,最后通过BitBlt绘制到真正的现实设备CPaintDC dc上显示出来。这样一来,我们只是看到了最后的效果,变化的过程看不到,闪烁自然就没了。

      另外一个值得注意的地方在于,为了使控件、雪花、主对话框背景能紧密结合,必须在其

内贴图缓冲的时候通过以下代码取得主对话框的目标位图的指针pBmp,并且,为了使得透

空贴图位置更准确,必须获取控件坐标位置并转换成相对于主对话框的(为什么?读者可

以自己先思考),否则,当控件位置改变的时候,其透空会失败:


      至此,MFC内实现雪花动画的原理讲解完成,如有任何疑问的地方,欢迎各位在我的博文

内提出。如哪位有更巧妙的方法或建议,也可以以邮件的方式和本人一起讨论,以便不断

改进和创新。