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