万星星@豌豆荚 欢迎加入我们
一个am,一个fm,大家不同频道......
微博:http://weibo.com/wanlianwen

很近没有更新了,闲话少说,直奔主题。

 

微软做任何技术的思路:在实现一个标准的时候,往往预留出一个通用的扩展机制。呃,貌似很多大公司都是如此,通过扩展把开发者跟自己捆绑。举例:微软的ie可以嵌入ActiveX控件、可以用BHO扩展;richedit中支持OLE扩展。这种扩展机制主要是基于其OLE框架,这也是微软操作系统框架的基石。开发层面目前的趋势是,淡化OLE强调.NET,有一种无奈叫骑虎难下,有一种错误叫脱离群众,在开发平台、技术百花齐放,开发资源极大丰富的今天,开发者对微软的依赖已经不那么强烈,以至于现在的Windows开发者有点小苦逼,尤其是C++开发者有一种被抛弃的感觉,扯远了。

 

谈谈OLE/COM/ACTIVEX的关系。很模糊,有一些说不清,有历史原因,也有普及程度关系。侯捷说玩模板有三境界:会用标准库,读懂标准库源码,会用模板做设计。我觉得COM相关的也是如此,使用COM组件往往是容易。我的理解:OLE是技术规范,COM是语言规范,而ACTIVEX则是用这2东东来实做的可服用组件的称谓。对于OLE的支撑主要在MFC库中,而ATL库则是更纯粹的OLE/COM框架。MFCOFFICE有一衣带水的关系,OFFICE的应用框架促使着MFC的发展(早期如此,但UI方面早已分道扬镳),OFFICE的应用模型也就是MFC的应用开发模型。

 

之所以提及MFCOFFICE,只是想说通用的扩展机制没有那么多条条框框,即便是ACTIVEX框架这种东西。对于OLE实践,也就是微软最热衷,其中Windows操作系统和OFFICE系列软件要最典型,其它则很牵强。OLE技术标准接口只有极少数是必须实现,而大部分则是可选实现或者部分实现,其中richedit更是如此。OLE对服务器和客户端都做了行为规范,如果一方(一般是服务器)自行决定如何实施,则另一方也只需对应实现。

 

呃,我说了这么多,只是为了阐述我的险恶用心,或许没人明白。ATL框架定义了四个标准导出函数用于规范注册、反注册、加载、卸载,这些跟实际的OLE功能无关,尤其是在richedit扩展中。或许你在网上诸多示例中看到用ATL模板创建一个控件然后如何简单的插入位图就以为掌握了核心科技,那么我就要泼冷水了,这些东西无关大局。既然Windows能用OLE搭建框架,既然MFC可以实践OLE,那么我们也可以用纯正的C++代码玩OLE,我的意思无非就是没必要遵循ATL,也没必要一定去注册一个东西,问题的核心不是这些东西,目前我们仅仅是为了插入一个动画。

 

Richedit是一个不完全的OLE实践,前面提到能完全实践OLE的框架不多。因为richedit实现了图文混排,所以在IM领域很受欢迎,尤其是早期(现在基于chromium的扩展或许可以改变现状)。Richedit是一个容器,可以容纳OLE控件进入,典型的扩展就是动画控件。基于ATL框架开发,你可以实现一个标准的控件,但当你面对一个非标准的容器时,那些条条框框显得不是那么重要,这也是为什么能做好动画控件不容易的原因。

 

根据我的调查(呃,通过实践,通过QueryInterface观察),我发现实现一个richedit中的动画控件只需要实现二个接口:IOleObjectIViewObject2,前者为了融入到richedit环境中,后者为了渲染显示。由于richedit默认只喜好无窗口模式,所以针对IOleInPlaceSiteWindowless之类的,你去实现意义也不大,因为人家容器不认你,当然还有IPersist系列接口,对于标准的环境有用(比如IDE),但这里并不是很需要,所以认清核心问题能减少很多困惑。更显然的是我的控件没有用ATL框架,因为此控件脱离了richedit环境生存的意义也不大,更有甚者我没必要让使其成为标准(也没可能),仅仅是为了在一个系统中的richedit中更好地展示。实现的接口越少,引入的麻烦越少,这样才能使精力集中在主要问题上。

 

综上所述,我的控件是一个C++类,只实现了两个接口:

 

X_BEGIN_INTERFACE_MAP(IMRichPicture, ObjectRootBase)
  X_INTERFACE_PART(IMRichPicture, IID_IOleObject, OleObject)
  X_INTERFACE_PART(IMRichPicture, IID_IViewObject, ViewObject)
  X_INTERFACE_PART(IMRichPicture, IID_IViewObject2, ViewObject)
X_END_INTERFACE_MAP()

 

 

其中大部分接口都可以无视,因为我们只需要这个控件在richedit中能够占位(长宽),能够展示(效率关键),至于其他的可编程、在位激活、对象识别都不重要。我观察了QQ的动画控件,呃,比现在网上流行的要改变很多(网上内容没有与时俱进)。现在的`QQ的动画控件很简单(后面会讲述如何找到这个控件),看起来只是作为一个占位工具,如何触发动画则是由host控制。观其接口:

 

interface IRichFrameObj : IDispatch {
    };
interface IRichPicObj : IDispatch {
        [id(0x00000001), propput, helpstring("property src")]
        HRESULT src([in] BSTR rhs);
        [id(0x00000002), propput, helpstring("property static")]
        HRESULT na([inlong rhs);
        [id(0x00000003), propput, helpstring("property autoHeight")]
        HRESULT autoHeight([inlong rhs);
        [id(0x00000004), propput, helpstring("property autoWidth")]
        HRESULT autoWidth([inlong rhs);
        [id(0x00000005), propput, helpstring("property maxAutoWidth")]
        HRESULT maxAutoWidth([inint rhs);
        [id(0x00000006), propput, helpstring("property onerror")]
        HRESULT onerror([in] BSTR rhs);
        [id(0x00000007), propput, helpstring("property objid")]
        HRESULT objid([in] BSTR rhs);
    };

 

IrichFrameObj的作用我不是很理解居然一个接口都没有而后者模糊的能够理解一些src大概就是动画图片路径,auto系列是为了动态缩放。现在的QQ只允许一个自定义动画,依据老衲猜测,因为自定义动画往往是截图,比较大,在一行容易引起点击时视图跳跃。再有其他的属性是为了识别所用,无法推测具体行为。

 

呃,事情看起来没有那么复杂,的确,我只实现了2个接口,而其中大部分也都是返回E_NOTIMPL,因为richedit确实没有那么标准,你实现的再标准也无济于事。当然richeit也在更新,win8sdk对其改动最大,但win7sdk也暴露了一些更早的功能,这或许是目前实现的最大亮点(技术含量,高风险高回报,一般人难以置信)。

 

对于动画控件阐述到此为止,或许很多人会很失望,但也仅仅如此,因为它本身什么都没有,尤其是在你真正明白之后,所以这里或许你会很失望,但是真正的内容就这么多,我也不知怎么添油加醋。

 

最后一个建议,希望尊重所有玩技术的:

1、中国官本位思想很严重,技术搞得不错(或许是运气)立马转管理

2、文人相轻

3、资本运作,体制运作,技术作用不明显

4、吃饱肚皮,难以维系理想

 

大道无形,大音希声,牛叉的技术很多都是巧工,而真正的产业才是大无畏的研发,我们只不过在投机取巧。

posted on 2012-08-05 15:15  法克给木  阅读(1440)  评论(0编辑  收藏  举报