SonicUI運行機制的粗略分析

來源:互聯網
上載者:User

在試用了一個開源的輕量級2D引擎庫SonicUI後,感覺它的執行效率不錯,因此對它的運行機制產生了興趣並做了一個簡要的分析。按照我的習慣思路都是針對一個特例來進行分析,這樣能夠起到抽繭剝絲的作用,在對分析對象有一個感性認識後再深入瞭解其它細節。
========================

一、唯一全域變數:CSonicUI,其它控制項為託管對象(IMAGE、WND_EFFECT、STRING、SCROLL_BAR、PAINT、ANIMATION、SKIN幾種)由CSonicUI執行個體負責管理

二、繪圖基礎:建立一個標準視窗(訊息函數WndProc),SonicWndProc為CSonicUI替換主視窗訊息函數(Attach/Detach將託管對象記錄並與視窗關聯)。前者處理WM_COMMAND、WM_ERASEBKGND、WM_DESTROY、WM_PAINT(此訊息中阻塞方式通知InternalWndProc完成實際繪圖工作);後者先預先處理WM_PAINT(僅記錄wParam中的PaintDC)、WM_ERASEBKGND(擷取無效地區大小)、WM_DRAWITEM、WM_NCDESTROY,然後分析所有託管對象(IMAGE、WND_EFFECT、STRING、SCROLL_BAR、PAINT、ANIMATION、SKIN幾種)並進行處理。另有一個與CSonicUI執行個體對象關聯的1X1彈出屬性視窗(訊息函數InternalWndProc)處理WM_TIMER、WM_SONIC_INTERNAL_EVENT、WM_SONIC_DETACH

三、一些技巧
1、如在訊息處理函數(如按鈕滑鼠按下事件)中商務邏輯處理較耗時,就會造成不能及時處理其它訊息(如按鈕滑鼠抬起事件)或不能及時重新整理(更嚴重可能還會造成多個無效地區合并),因此需要SonicWndProc先記錄繪圖DC及無效地區後再由WndProc用自訂訊息(WM_SONIC_INTERNAL_EVENT)通知另外一個視窗(InternalWndProc)來完成實際繪圖工作(對於需要即時重新整理的如按鈕控制項用SendMessage,否則用PostMessage)
2、訊息機制類似QT的訊號槽機制,QT進行事件和槽串連的函數原型如下
bool QObject::connect(const QObject *sender, const char *signal,
                      const QObject *receiver, const char *method,
                      Qt::ConnectionType type)

四、滑鼠移進按鈕(CSonicString對象執行個體)流程
1、CSonicUI::SonicWndProc(WM_MOUSEMOVE)
=>CSonicString::MessageFilter
=>CSonicString::OnWndMsg
=>CSonicString::OnMouseMove
=>ISonicBaseData::FireDelegate(DELEGATE_EVENT_MOUSEENTER)
=>PostMessage(WM_SONIC_INTERNAL_EVENT, wParam=ISonicPaint執行個體對象指標, lParam=DELEGATE_EVENT_MOUSEENTER)
註:CSonicUI::InternalWndPro響應訊息後調用ISonicBaseData::OnDelegate時,因為CSonicString沒有託管DELEGATE_EVENT_MOUSEENTER事件(託管了DELEGATE_EVENT_PAINT事件),相應的ISonicBaseData::m_mapDelegate表中也無事件函數並直接返回。因為是非同步作業這個可能在第2步前或後執行

2、CSonicString::ChangeStatus(同步執行第一步後續操作)
=>CSonicString::KillInternalTimer
=>CSonicString::ForceRedraw
=>CSonicString::Redraw
=>CSonicPaint::Redraw
=>CSonicUI::Redraw
=>InvalidateRect

3、CSonicUI::SonicWndPro(WM_PAINT)
註:CSonicString對象不處理此訊息,直接轉下一步

4、CallWindowProc(OldProc)
註:在WndProc中對WM_PAINT有一個技巧,用ApiHook的方式替換掉了BeginPaint和EndPaint
註:BeginPaint會發送一個WM_ERASEBKGND訊息給視窗將無效地區刷成背景色

5、SonicUIDemo!WndProc(WM_PAINT)
=>CSonicString::TextOutA
=>CSonicPaint::Draw
=>CSonicPaint::InternalDraw
=>ISonicBaseData::FireDelegate(DELEGATE_EVENT_PAINT)
=>SendMessage(WM_SONIC_INTERNAL_EVENT, wParam=ISonicPaint執行個體對象指標, lParam=DELEGATE_EVENT_PAINT)

6、SonicUI::InternalWndPro(非同步執行第一步或同步執行第五步後續操作)
=>ISonicBaseData::OnDelegate
=>CSonicString::OnRender
=>CSonicString::Render
=>CSonicString::RendImage
=>CSonicPaint::Draw
=>CSonicPaint::InternalDraw
=>ISonicBaseData::FireDelegate(DELEGATE_EVENT_PAINT)
=>SendMessage(WM_SONIC_INTERNAL_EVENT, wParam=ISonicPaint執行個體對象指標, lParam=DELEGATE_EVENT_PAINT)
註:在ISonicBaseData::OnDelegate中有一個技巧,用彙編計算託管對象的託管渲染函數地址,在這一步是CSonicString::OnRender畫hover狀態圖,在下一步則是CSonicString::RenderText畫tooltip文字及背景
CSonicString有兩個ISonicPaint受管理的執行個體對象m_pOrigin和m_TextCache分別用於繪圖和文本,

7、CSonicUI::InternalWndPro(同步執行第六步後續操作)
=>ISonicBaseData::OnDelegate
=>CSonicString::RenderText
此處畫tooptip文字及背景色

8、END

五、滑鼠移出按鈕流程
同上

六、主要資料結構

七、有關髒矩形處理的類CSonicPaint,由CSonicUI::CreatePaint建立

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.