在VC++中使用Flash界面

最近的一个项目,想通过在VC中嵌入Flash的方式实现程序界面。以前曾经做过Flex的B/S项目,知道一些Flash和IE浏览器之间的工作方式。可是接触了以ActiveX方式实现的Flash编程时,自然而然想当然的走了很多的弯路。很多貌似很复杂的问题,在绕了很多的圈子之后才发现,原来实现起来往往只需要一行代码。项目还需进行,特意在此把心得记录下来。
 
一、Flash同VC之间的数据通讯。
同大多数的ActiveX控件一样,VC为Flash实现了一个CWnd的包装:CShockwaveFlash,该类实现了Flash ActiveX控件的所有功能。在AS3问世之前,Flash同宿主之间的通讯只有FSCommand一种方式,而且是异步的,更没有返回值可言。因为项目中需要VC为Flash提供大量的数据库查询,返回结果通过XML进行传递。因此,FSCommand无疑是不方便的。
 
AS3推出的外部API调用方式:ExternalInterface,极大的简化了编程方式。ExternaleInterface是同步的调用,并可以返回调用结果。需要说明的是,同步调用是以牺牲性能为代价的,因为这涉及到大量的CPU周期占用)。我曾经在Flex项目中,利用ExternalInterface实现了IFrame在Flash的嵌入调用,从而达到在Flash中显示HTML的问题。
 
CShockwaveFlash为ExternalInterface提供了一个事件接收器(event sink):FlashCall。FlashCall事件只有一个参数:request,而且我们会发现,在Flash中通过ExternalInterface的调用,是通过XML的方式进行封装,然后传递到request中的。为了获得调用的方法名和参数,你必须解析request封装的XML包。
 
不过奇怪的是,处理FlashCall事件的是一个void方法。要返回数据,你需要调用SetReturnValue方法。返回的数据也必须是XML格式,且必须符合Flash的规范。如果要返回XML结果集,把XML封装到<string></string>中,然后在Flash中通过new XML(str)的方式动态生成。
 
二、屏蔽Flash的右键菜单
这是个恼人的问题,我不希望用户在软件界面中弹出Flash右键菜单。在VC中,虽然Flash控件提供了SetMenu方法,通过传入FALSE屏蔽大部分的菜单项,但遗憾的是,“关于”和“设置”菜单无法去掉。
 
为了实现这个功能,我查阅了大量的资料。按照一般的想法,右键菜单的生成应该经过某种消息处理的流程。我先是重载了CShockwaveFlash类的WndProc方法,并在其中跟踪消息流,结果造成IDE死机。我做出了一个错误的决定,我认为这个消息一定可以在其它地方截获,于是我又费了很大的周折,特意实现了自己的CControlSite类,结果依然让人失望。
 
后来下载了一个Delphi下的TShockwaveFlashEx组件,才发现该组件是通过截获组件的WM_RBUTTONDOWN消息实现的菜单屏蔽。这就是说,让用户的右键消息干脆不传到Flash控件中去。简单而直接的方法。
 
在VC中实现起来更简单些。直接从CShockwaveFlash派生自己的类(不建议直接修改CShowwaveFlash类),然后捕获WM_RBUTTONDOWN消息,直接在消息处理函数中注释掉父类的方法调用。然后修改Flash对象的类型为你的派生类即可。
 
甚至可以更简单些。直接在对话框中响应WM_MOUSEACTIVATE消息,然后在处理函数中判断message参数的值,如果是WM_RBUTTONDOWN,则返回MA_ACTIVATEANDEAT(激活控件,吃掉消息。 http://msdn2.microsoft.com/en-us/library/ms645612.aspx)。
 
三、调整窗口大小时防止Flash控件闪烁
在Dialog的WM_SIZE响应中,把Flash控件布满整个窗口。可是这个简单的实现却造成了Flash界面的频繁闪烁。在Delphi的TShockwaveFlashEx组件中,作者是通过覆盖组件的CreateWnd方法实现的,在对话框Resize事件中,调用这个重载的CreateWnd方法。
 
可是,在VC中如何实现呢?为此,我在google上苦苦搜索了好几天。关于ActiveX控件闪烁的问题,网上有很多的解决方案。很多方案都是建议同时重载控件和对话框擦除背景事件,然后写一些代码防止控件重绘自身。也有一些方法是通过GDI的思路,在内存中通过bitblt的方式避免闪烁。看到最后很伤心,怎么会这么麻烦呢。
 
今天在网上找到一篇文章: 解决Windows 程序界面闪烁问题的一些经验,文中讲到造成界面闪烁的第二个原因:

复杂的界面有多层窗口组成,当windows在窗口改变大小的时候是先重画父窗口,然后重画子窗口,子父窗口重画的过程一般无法在一个刷新周期内完成,所以会呈现闪烁。我们知道父窗口上被子窗口挡住的部分其实没必要重画的。

解决方法:给窗口加个风格 WS_CLIPCHILDREN ,这样父窗口上被子窗口挡住的部分就不会重画了。如果同级窗口之间有重叠,那么需要再加上 WS_CLIPSIBLINGS 风格

 

我赶紧到项目中把Flash对话框的窗口风格加上WS_CLIPCHILDREN,编译后运行,成功了!感谢作者,让我终于睡了一个安稳觉。
 
四、DEBUG状态是总是报Assertion失败。
这个问题困扰了我一整天。我的系统上安装了Flex SDK,因此,注册的Flash控件是调试版。不知什么原因,在每次关闭对话框之后,系统总是报cmdtarget.cpp文件中的控件引用值不为1错误,从而造成断言失败。
 
我以为是代码的问题,重建了一个项目,什么代码都没写。运行,关闭,断言错误。因为之前的VC出现了一个奇怪的问题:打开对话框命令总是出现非法操作。反复重装VC都不能解决,最后在网上看到可能是安装的visio 2003冲突,卸载visio 2003后问题解决。我开始怀疑是不是我之前的折腾把系统搞乱掉了。我又重装了一次VC,再次编译运行,问题再次出现。我都快疯了。
 
在没疯之前,我决定到同事的电脑上试一下。生成的程序运行没有问题。把我生成的代码拷贝过去运行,没有问题。我突然意识到,是不是Flash控件的问题。卸载重装后,问题解决。我的天!
 
(待续。。。)
 
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页