研究背景
自職業生涯起到現在,我參與過三個im類產品,其中我主要負責的是界面庫開發。眾所周知,im軟件中有一個非常重要的控件用于消息展示,實現方式無外乎基于richedit(目前這一類為主要方式,代表:QQ)、基于webbrowser(代表:GTalk),可能會有基于WebKit的,我沒有刻意去搜集。很多時候對于相對簡單的情況,比如在游戲中,完全可以自己繪制。
我曾經模仿過GTalk的實現方式,由于當時自己經驗欠缺以及與公司寫頁面的人溝通上的問題,效果不是那么滿意,僅僅夠用,后來自己離開也沒再繼續做這方面研究。機制上這種方式是可行的,native端事情不多。
后來的工作中,主要是基于richedit在做,都是安排其他人負責。在開發過程中,遇到種種問題,用過各種不優雅的“伎倆”,由于欠缺OLE知識,做的人很痛苦,找不到樂趣。微軟官方有一個例子,然而只披露了使用技巧的冰山一角;codeproject也有少的可憐的幾個例子,經不住商業化應用;互聯網搜索的一些文章大多都是簡單的插入圖片等,聊勝于無。
《基于Chrome開源提取的界面開發框架》系列文章獲得了不少支持,在提取過程中我自己也成長很多。抽取出來的引擎要想用于商業化開發,我個人覺得欠缺的主要是富文本渲染這一塊,這使我開始研究richedit。斷斷續續,期間各種事情,幾經放棄。后來一個網友在這個問題上又找到我,臨時的幫助他解決問題之后,不禁感嘆,為什么互聯網上找不到一個優雅的解決方案甚至是深入的介紹?
網友megax的文章http://www.shnenglu.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內核框架是否可以工作。
測試的接口如下:
這一篇到此為止!依然是閑話多,干貨少。我會努力的!