1 创建解决方案
创建一个空的解决方案,名称GifSolution。将来包含控件项目和测试项目。
2 创建ATL项目
解决方案视图-右击解决方案-添加-新建项目,弹出的对话框中选ATL项目,名称为GifAnimate确定。弹出的对话框中选择DLL服务器(可选允许合并代理存根,这样不会产生代理dll),完成后编译,这样工程框架就完成了。
3 添加新组件
3.1 一点要说明的
组件分有窗口的和无窗口的,这里应该用有窗口的,所以添加组件的时候,外观不要基于none,最好基于CStatic。因为gif是动态的,应该用另一个线程绘制,这样不影响主线程响应消息,绘图更加流畅。
两种窗口的区别:无窗口的控件用父窗口做自己的窗口;用父窗口的DC绘图;通过DEFAULT_REFLECTION_HANDLER()把消息反馈给父窗口以进行响应。有窗口的控件,多一个CContainedWindow m_ctlStatic变量作为显示窗口;在BEGIN_MSG_MAP / END_MSG_MAP之间,通过ALT_MSG_MAP(1)宏映射消息处理(1为控件m_ctlStatic构造时候的内部标记,因为可能有多个窗口,默认1个,用户可以自己添加)。
3.2 添加组件对象
为GifAnimate项目添加类-选择ATL控件,点击添加,弹出对话框。
第一卡:组件名称GifAniControl
第二卡:支持连接点(因为要通知客户端)
第三卡:默认接口
第四卡:外观基于Static,可插入(在注册表注册为OLE插入对象,可以插入Office)
第五卡:实现固有属性-背景色、边框色、边框可见性
确定后,编译通过。
3.3 为组件添加方法
类视图-右键点击控件接口-添加-方法,分别添加Play Stop Pause Continue PrevFrame NextFrame函数,以操作gif图片。添加IsPlaying函数,添加LoadGifFromFile LoadGifFromStream函数
3.4 为组件添加属性
注意:在idl文件里定义一个枚举,指明播放方向。
类视图-右键点击控件接口-添加-属性,分别添加Loop(循环次数) DelayTimeFactor(时间因子) PlayDirection(播放方向)等属性。
对于每一个属性,控件类增加了一对函数,去读写属性get/put_XXX,真正的变量要我们自己写的。
4 实现绘图
添加GifImage类,用于实现绘图功能。
在控件类里,添加一个GifImage类型的变量,主要用于对图片的控制。
完成组件接口函数和属性的调用。
把窗口的句柄给GifImage,让它实现绘图。
(对于无窗口控件,修改组件的OnDraw函数,实现绘图)
编译通过就可以测试了(由于用到了GDI+,用ActiveX控件测试容器无法调用函数)。
5 添加测试项目
右键点击解决方案-添加-新建项目,弹出的对话框中选MFC EXE项目,名称GifTestDlg。创建一个基于对话框的项目。
导入DLL:#import "../GifAnimate/Debug/GifAnimate.dll"
初始化COM和GDI+
在对话框初始化的时候创建控件,并设置属性等。
编译运行成功。
6 添加事件
第二步已经支持连接点,idl文件里会有事件接口
6.1 为事件接口添加函数(声明)
类视图-右键点击lib接口里的事件接口-添加-方法,添加一个Click函数,参数为long型的x,y坐标。产生的效果是,在idl文件里,向导为事件接口添加了一个点击函数。
6.2 生成代理类函数
生成一个代理类,实现函数。[Only in VC6, VS2008自动完成]
类视图-右键点击控件类-添加-添加连接点,在对话框选中以上提到的连接点,确定。
代理类会包装一个函数Fire_Click,触发客户端。
6.3 触发事件(调用函数)
响应控件类的WM_LBUTTONDOWN消息,调用代理类的Fire_Click函数。
6.4 客户端关注事件
客户端用ATL或者MFC完成一个接收器GifSink,连接、工作、断开。
7 添加属性页
完全可以不做而通过程序设置属性,做这个是给懒程序员用的,或者只是让组件使用更方便。
7.1 添加属性页卡片
添加-类-ATL属性页-确定,弹出对话框中添加简称,修改组件属性和标题,确定。
系统生成相关的对话框卡片资源、对应对卡片类、idl相关内容、注册脚本等。卡片类有一个Apply函数,用于接受属性设置。
7.2 设置属性
修改对话框,增加新控件等等。然后处理数据变化,例如:处理Edit的EN_CHANGE事件,设置page组件的脏数据标记(修改但没有确定)。最好并完成Apply函数。
7.3 手工把属性页添加到控件
在控件类.h添加如下代码
PROP_ENTRY("Sides", 1, CLSID_GifProp)
8 说明
1. 本文只是举例说明开发过程,抛砖而已。
2. 样例只是框架,不能直接使用,所有代码没有经过测试
3. 样例接收器GifSink和属性页卡片没有完成,懒了,呵呵
4. 样例背景等很多属性没有实现
5. 使用了GDI+,但GDI+的Image类的SetActiveFrame函数有问题,网上貌似没有解决办法。Debug版本不影响使用,Release版本没有测试。如果有兴趣,可以使用IPicture接口,网上很多。
6. 本文和本样例版权crybird所有,引用处请标记crybird。