研究背景
自职业生涯起到现在,我参与过三个im类产品,其中我主要负责的是界面库开发。众所周知,im软件中有一个非常重要的控件用于消息展示,实现方式无外乎基于richedit(目前这一类为主要方式,代表:QQ)、基于webbrowser(代表:GTalk),可能会有基于WebKit的,我没有刻意去搜集。很多时候对于相对简单的情况,比如在游戏中,完全可以自己绘制。
我曾经模仿过GTalk的实现方式,由于当时自己经验欠缺以及与公司写页面的人沟通上的问题,效果不是那么满意,仅仅够用,后来自己离开也没再继续做这方面研究。机制上这种方式是可行的,native端事情不多。
后来的工作中,主要是基于richedit在做,都是安排其他人负责。在开发过程中,遇到种种问题,用过各种不优雅的“伎俩”,由于欠缺OLE知识,做的人很痛苦,找不到乐趣。微软官方有一个例子,然而只披露了使用技巧的冰山一角;codeproject也有少的可怜的几个例子,经不住商业化应用;互联网搜索的一些文章大多都是简单的插入图片等,聊胜于无。
《基于Chrome开源提取的界面开发框架》系列文章获得了不少支持,在提取过程中我自己也成长很多。抽取出来的引擎要想用于商业化开发,我个人觉得欠缺的主要是富文本渲染这一块,这使我开始研究richedit。断断续续,期间各种事情,几经放弃。后来一个网友在这个问题上又找到我,临时的帮助他解决问题之后,不禁感叹,为什么互联网上找不到一个优雅的解决方案甚至是深入的介绍?
网友megax的文章http://www.cppblog.com/megax/archive/2012/03/22/168601.html中关于制作编辑器方面知识提及的http://www.catch22.net/tuts/neatpad让我着实佩服,老外对待研究的态度真的很严谨,分享的开发性和持续性方面远远胜于我们。系列文章中的绝大多数概念知识我都接触过,然而很多没有深究,经验远远不如文章主人。
Richedit的研究的大部分知识都在OLE方面。现在计算机的发展,技术的百花齐放,使得Windows平台不再那么大行其道,Windows技术也不再那么不可一世,Mfc越来越被抛弃,Windows程序员诚惶诚恐,新生代早早把自己定位在更炫更酷更激情的技术平台。在Windows Native开发没有彻底失宠前,我打算把自己死啃得来的OLE知识发挥“余热”,对richedit这个东西应用于im领域的问题解决一下,希望对其他人有帮助,也希望没有重复造轮子。
研究目标
Richedit是Windows底层的组件,甚至在2004年泄漏的Win2K代码中都没有,它是独立于edit组件的,而edit位于ntuser中,亦相当底层,虽在泄漏代码中出现,然而抽取出来的可能性不大。从某种角度来讲,Reactos 就是抄袭的这份代码,明眼人可以从其死灰复燃的更新列表中发觉。很奇怪的是Reactos 的代码中有richedit,我也移植过,只是后来发现功能实在太弱,无可用性,遂放弃,至于Wine 是不是抄袭这份代码,我无从得知,也没精力再去跟踪。
Richedit 的接口相当稳定,我在Win8中试验过完全兼容,我想它应该会持续很久,所以值得去好好研究一把。
《基于Chrome开源提取的界面开发框架》的view框架,如果能有一个rtf格式的渲染利器,配以ole的展示,我想足以成为互联网商业开发的UI解决方案。
Richedit 就机制上来讲跟WebKit一样,或者应该反过来说。Richedit窗口本身是对ITextServices的封装,实现ITextHost接口与ITextServices交互提供平台支持。ITextServices的支持分两大类:基于文本的ITextDocument和基于ole的IRichEditOle。作为ole容器,提供的功能主要通过实现几个接口完成的,包括:IOleClientSite、IAdviseSink、IOleInPlaceSite,缺省的Richedit 貌似不支持定位激活,想要达到激活效果必须支持最后一个接口。与剪贴板和拖拽数据打交道需要支持统一数据传输接口IDataObject。
研究主要参考对象为QQ,目标为:支持粘贴格式、动画ole控件、定制ole菜单、拖拽、文本操纵、窗口/无窗口的统一支持等,我会在下一篇列出详细的大纲。
已做工作
OLE标准提供了大量工业化标准接口以及繁杂的交互规范,事实上除了微软(以office系列产品为典范),鲜有软件全盘实施。可以说MFC的大部分工作都是用在实现OLE,所以其臃肿大抵源于此,不得不臃肿,早些年我接触wtl后得出,MFC - WTL == OLE,或许还有一些打印等方面设施,但我不觉得这些是主要特性。以我现在眼光来看待,把MFC拆分开,其集合类、打印框架、COM支持、OLE支持、文档/视图/框架模板(尽管现在用的极少,大多在行业软件领域)、进程/线程/模块状态管理等,都还不错,呃…,貌似我快把它说全了,不好意思,我的老毛病又犯了,其实在心底,我还有那么一点不舍,即便我很多年没有用它开发商业软件了。我从MFC学到的东西太多太多,以至于我不肯说它的坏话。
再一次,我选择了从MFC中抽取代码。我尝试过直接使用MFC,静态链接以便偷偷的不告诉别人,以免“破坏形象”。但我不觉得我能做到,原因就是整个MFC耦合的比较紧密,我不想或者无法使用整个框架来对外提供服务,所以我不得不制造小轮子。我也试过直接实现,但是工作量还真不小,我怕自己等不及,故再次祭出看家本领,顺藤摸瓜,牵出一个支持OLE的最小内核,经过1-2周我能腾出的时间,终于做到了,于是我写下了开篇,后面我需要把整个思路刻画出来。下面是一个示例,插入浏览器,支持定位激活:
这个例子不具备任何说明性,只是用来测试最小的OLE内核框架是否可以工作。
测试的接口如下:
这一篇到此为止!依然是闲话多,干货少。我会努力的!