最近工作上比較忙,加之編碼任務(wù)較多,沒來得及繼續(xù)之前的講解。抽出時(shí)間把這最重要的一部分東西做個(gè)闡述。行文以基本的編程思維及個(gè)人思考過程為線索。
眾所周知,RichEdir強(qiáng)大在于其圖文混排(在這里不跟Word、HTML比),其中的圖替換為動(dòng)態(tài)圖的核心問題就歸結(jié)于如何高效刷新。我們知道GDI操作是最消耗CPU的,所以刷新整個(gè)RichEdit窗口是不可取的,其副作用會(huì)導(dǎo)致更嚴(yán)重的閃爍問題。解決問題的思路很簡(jiǎn)單:類似于拖拽時(shí)候在屏幕繪制異或線,我們的動(dòng)畫重繪時(shí)不請(qǐng)求RichEdit,而直接在其窗口的DC上繪制當(dāng)前動(dòng)畫幀,此時(shí)缺少是如何確定該OLE的位置,這個(gè)是所有問題的關(guān)鍵。先看下面這幅圖:

假定1-5全部都是GIF圖片,非GIF可以暫時(shí)無視,這個(gè)后面大家會(huì)非常清楚如何處理。在這個(gè)過程中,2不見了,而4是新出現(xiàn)的。對(duì)于4新出現(xiàn)時(shí),RichEdit自身肯定會(huì)觸發(fā)其:
Draw(
DWORD dwDrawAspect, LONG lindex, void* pvAspect,
DVTARGETDEVICE* ptd, HDC hicTargetDev, HDC hdcDraw,
LPCRECTL prcBounds, LPCRECTL prcWBounds,
BOOL (__stdcall *pfnContinue)(DWORD_PTR dwContinue),
DWORD_PTR dwContinue)
這個(gè)時(shí)候,我們知道新的GIF圖片進(jìn)入可視區(qū),可以把它添加到集合中。對(duì)于2的動(dòng)畫觸發(fā)時(shí)間到來時(shí),我們可以確定其位置且與可視區(qū)比對(duì),發(fā)現(xiàn)其不再可視區(qū),則從集合中移除。這樣就可以得到一個(gè)接近于(略大于)當(dāng)前視口中的動(dòng)畫控件集合,當(dāng)有新的動(dòng)畫觸發(fā)時(shí)間到來時(shí),我們可以先檢查其是否在可視區(qū),如果不在則不用GDI操作,僅僅更新其當(dāng)前幀。當(dāng)然這些工作你也可以不做,但是在動(dòng)畫控件數(shù)量大的時(shí)候效率可能略有下降,主要是查找的過程(索引、位置)比較耗時(shí)。
如何確定一個(gè)OLE的位置呢?由于我們插入OLE都使用了REO_BELOWBASELINE標(biāo)志,也就是跟當(dāng)前行的底部對(duì)齊,所以O(shè)LE左下角位置的精確度對(duì)我們來說很重要。看下圖:

假設(shè)圖中黑框是一個(gè)OLE對(duì)象,其字符索引為CPN,假定第N+1行的第一個(gè)字符索引為CPN1,那么OLE左下角坐標(biāo)={PosFromChar(CPN).x, PosFromChar(CPN1).y },PosFromChar這個(gè)是RichEdit提供的。問題的關(guān)鍵是最后一行怎么計(jì)算?此時(shí)沒有第N+1行。對(duì)于這種特殊情況,主要是Y坐標(biāo)的計(jì)算,可以這樣考慮:Y=RichEdit內(nèi)容高度-滾動(dòng)條位置。猜測(cè): 計(jì)算內(nèi)容高度可能比較耗時(shí),故QQ的聊天消息顯示部分強(qiáng)制在底部加了一行,以避免這種情況出現(xiàn)。
得到左下角位置以后,可能你會(huì)覺得就萬事大吉了。錯(cuò)!還有一個(gè)關(guān)鍵點(diǎn)!我們可以通過OLE的接口GetExtent得到其大小,然而這個(gè)大小沒有考慮縮放比例,所以你需要根據(jù)當(dāng)前縮放比例進(jìn)行計(jì)算,而這個(gè)計(jì)算牽扯到浮點(diǎn)數(shù)運(yùn)算,過程中的來回不僅麻煩而且不精確,所以O(shè)LE的可視大小要想非常精確是不能通過計(jì)算來的。我們前面知道OLE繪制的時(shí)候會(huì)傳入可視范圍,假如我們保存下來是不是就可以解決問題了呢?當(dāng)然,顯然,你可以試試!
這些問題主要原因是RichEdit的很多接口方法沒有暴露,而Win8的SDK會(huì)做重大升級(jí),很多之前的問題都會(huì)變成不是問題,或許還會(huì)引起更多的新特性,但是動(dòng)畫本身的邏輯還是需要自己實(shí)現(xiàn),或者會(huì)簡(jiǎn)單許多,至于多少我還尚不清楚,但是目前來看這種方案效率足夠!
到了這里,核心技術(shù)應(yīng)該大白天下,整個(gè)過程,我追求了位置的精準(zhǔn)度,并據(jù)此獲得最小可視集合進(jìn)行刷新優(yōu)化。
最新SDK&Demo,參見:http://code.google.com/p/im-solution/。希望你會(huì)喜歡!
posted on 2012-09-08 18:10
萬連文 閱讀(4831)
評(píng)論(16) 編輯 收藏 引用 所屬分類:
小作品 、
richedit