我們知道Windows的窗口消息處理函數(shù)是C方式, 面向過程的, 所以窗口框架的基本任務(wù)就是將它轉(zhuǎn)成面向?qū)ο蟮姆绞剑?確切的說如何將消息處理函數(shù)第一參數(shù)HWND轉(zhuǎn)成對象指針。
關(guān)于這個問題, 其實網(wǎng)上大家已經(jīng)說濫了, 這里只是簡單記錄一下。
Map方式:MFC就是采用這種方式, 就是建立一張從HWND到CWindow*的映射表, 每次收到消息都從Map中根據(jù)HWND找到CWindow*, 再進行調(diào)用
UserData的方式:
CreateWindow時將最后一個附加數(shù)據(jù)設(shè)置為對象CWindow* 指針, 當收到第一個消息WM_NCCREATE時, 取出傳過來的附加數(shù)據(jù)指針, 將該指針設(shè)置成窗口的UserData, SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(pThis))
, 后面收到任何消息就可以直接調(diào)用GetWindowLongPtr(hWnd, GWLP_USERDATA)
取出窗口指針, 進行面向?qū)ο蠓绞降恼{(diào)用。
Thunk方式:這是ATL采用的方式,通過匯編代碼,直接將窗口消息處理函數(shù)的第一個參數(shù)HWND改寫成CWindow*, 然后進行面向?qū)ο蠓绞降恼{(diào)用, 原理可以見我以前寫的 理解ATL中的一些匯編代碼
最近工作中要寫一些簡單窗口相關(guān)的代碼, 考慮用什么方式封裝窗口過程:
MFC肯定不引入, map方式也不考慮。
UserData方式太低效 ,而且窗口的UserData讓框架用了,我們其他地方可能還要用呢。
ATL的Thunk方式不錯, 但是我們不想引入COM, 也不想用ATL的庫和代碼。
原始的 C API方式, 依賴性和效率都最佳, 可惜就是不是面向?qū)ο蟮摹?br />
各有優(yōu)缺,怎樣才能熊掌和魚翅兼得?
最后決定把ATL中窗口Thunk相關(guān)的核心代碼剝離出來, 做一個完全獨立的最基本窗口框架。我們框架的基本目標是可以讓我們方便的開發(fā)一些簡單的窗口, 所以去掉了ATL窗口中一些不常用或是可替代的東西, 只留下必須和最有用的。簡單說來,把ATL中的CWindow給去掉了,它只是窗口API的封裝, 我們可以直接調(diào)用API來實現(xiàn);把CWinTraits給去掉了,因為它只是窗口風格的封裝; 把SubClass和SuperClass也去掉了, 我們的簡單窗口用不到這個特性; 把Dialog, Container和COM相關(guān)的都去掉了, 這些都不是窗口的核心部分。最后只留下,窗口注冊創(chuàng)建, thunk和消息映射相關(guān)的代碼。
測試了下,這個窗口框架基本上只有2個核心文件,完全獨立, 可以直接放到任何現(xiàn)有框架中使用(ATL/WTL中使用可能要改下內(nèi)部一些類名, 但是用了ATL/WTL肯定就不用這個框架了)。
posted on 2013-09-08 14:47
Richard Wei 閱讀(4405)
評論(11) 編輯 收藏 引用 所屬分類:
windows desktop