最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

【滴水基礎(chǔ)】5.MFC(2)

2023-03-25 19:59 作者:沙漠里的鯨  | 我要投稿

第九:MFC源碼分析

#MFC的WinMian分析

---注意:CWinThread* pThread = AfxGetThread()和CWinApp* pApp = AfxGetApp();

---都是獲取的全局對(duì)象theApp的虛擬內(nèi)存地址:因?yàn)橐粋€(gè)進(jìn)程里面存在一個(gè)主線程,AfxGetThread()返回的是當(dāng)前界面線程對(duì)象的指針。
---AfxGetApp()返回的是應(yīng)用程序?qū)ο?/strong>的指針,如果該應(yīng)用程序(或進(jìn)程)只有一個(gè)界面線程在運(yùn)行,那么這兩者返回的都是一個(gè)全局的應(yīng)用程序?qū)ο笾羔槨?br>

---查看pApp:指向的是CMyApp的首地址

---但是后面還有父類CWinThread,已經(jīng)CWinApp的CRuntimeClass結(jié)構(gòu)體classCWinApp的地址(支持RTTI和動(dòng)態(tài)創(chuàng)建)

---當(dāng)然也存在:當(dāng)前類的消息消息映射結(jié)構(gòu)體_messageEntries和獲取自己和父類消息映射的messageMap

---AfxGetApp()獲取當(dāng)前進(jìn)程的位置(AfxGetThread()本質(zhì)也是調(diào)用AfxGetApp())

_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp(){return afxCurrentWinApp; }

---而afxCurrentWinApp是個(gè)宏定義,位于src\..\..\atlmfc\include\afxwin.h

---AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow)將參數(shù)傳遞給當(dāng)前的全局對(duì)象theApp的成員變量中

---總結(jié):

---創(chuàng)建全局對(duì)象theApp,然后進(jìn)入AfxWinMain()

---通過(guò)AfxGetApp()獲取當(dāng)前進(jìn)程/線程的內(nèi)存地址(theApp的地址)

---通過(guò)AfxInit()將AfxWinMain的四個(gè)參數(shù)賦值給theApp的成員變量

---在InitInstance創(chuàng)建窗口對(duì)象后,會(huì)調(diào)用窗口對(duì)象(CFrameWnd)的構(gòu)造函數(shù)

---在構(gòu)造函數(shù)里面調(diào)用Create()的CreateEx()創(chuàng)建窗口

---里面先用PreCreateWindow()自定義窗口類和注冊(cè)窗口類(本質(zhì)是Windows的HWND窗口)

---然后調(diào)用AfxHookWindowCreate創(chuàng)建消息鉤子,所有DispatchMessage消息被_AfxCbtFilterHook截獲

---SetWindowLong設(shè)置窗口過(guò)程為AfxWndProc,并保存原窗口過(guò)程在窗口類成員變量m_pfnSuper中,這樣形成一個(gè)窗口過(guò)程鏈,將MFC的窗口對(duì)象和Windows的窗口對(duì)象進(jìn)行綁定

---Windows消息送給AfxWndProc窗口過(guò)程之后,AfxWndProc得到HWND窗口對(duì)應(yīng)的MFC窗口對(duì)象(CFrameWnd的子類)。

---然后調(diào)用OnWndMsg搜索根據(jù)本對(duì)象的messageMap,迭代搜索該MFC窗口對(duì)象和其基類的消息映射數(shù)組_messageEntries[]

---最后,判定它們是否處理當(dāng)前消息,如果是則調(diào)用對(duì)應(yīng)的消息處理函數(shù),否則,進(jìn)行缺省處理

#為什么在InitInstance()里面要Return True?

---消息循環(huán)(CWinThread是CWinApp的父類

---進(jìn)入CWinThread::Run()

---在Win32中的WinMian中,通過(guò)GetMessage獲取消息,注意GetMessage()是一個(gè)具有同步行為的函數(shù),如果消息隊(duì)列里面沒(méi)有消息,會(huì)一直等待,直到消息的出現(xiàn)才返回

---而PeekMessage():不管消息隊(duì)列里面是否存在消息,都會(huì)立即返回(就不會(huì)導(dǎo)致線程出現(xiàn)睡眠狀態(tài),注意:睡眠狀態(tài)下的線程下面的代碼不會(huì)執(zhí)行

---如果消息隊(duì)列中沒(méi)有消息,PeekMessage()返回0,不會(huì)導(dǎo)致線程處于睡眠狀態(tài)。

---對(duì)于virtual BOOL?OnIdle( LONG lCount );
---返回值:如果要接收更多的空閑處理時(shí)間,則返回非零值;如果不需要更多的空閑時(shí)間則返回0。
---參數(shù):lCount 該參數(shù)是一個(gè)計(jì)數(shù)值,當(dāng)應(yīng)用程序的消息隊(duì)列為空,OnIdle函數(shù)被調(diào)用時(shí),該計(jì)數(shù)值就增加1。
---每當(dāng)一條新消息被處理時(shí),該計(jì)數(shù)值就被復(fù)位為0。你可以使用lCount參數(shù)來(lái)確定應(yīng)用程序不處理消息時(shí)空閑時(shí)間的相對(duì)長(zhǎng)度。

---本身OnIdle( LONG lCount )是一個(gè)虛函數(shù),如果想要執(zhí)行空閑時(shí)處理,則重載這個(gè)成員函數(shù)。

---Run()是MFC的控制中心,而PumpMessage()又是Run()的核心,所以從MFC的真正控制中心是PumpMessage()

---PumpMessage()的核心:PreTranslateMessage(&m_msgCur)

---查看PreTranslateMessage(&m_msgCur)

---正是有了PreTranslateMessage(),才使得MFC能夠靈活的控制消息的分發(fā)模式,可以說(shuō),PreTranslateMessage()就是MFC的消息分發(fā)模式

---根據(jù)不同的窗口(桌面、MFC、Dialog)進(jìn)行處理

---查看WalkPreTranslateTree()消息進(jìn)行處理

---作用:將傳統(tǒng)的Win32的窗口過(guò)程函數(shù),改為消息映射,而WalkPreTranslateTree()的作用就是

#Run()總結(jié)

---只有MFC窗口(繼承于CFrameWnd)才會(huì)WalkPreTranslateTree()遍歷窗口的父類

---其它窗口如桌面直接DispatchMEssage、dialog窗口直接PreTranslateMessage()

---Windows窗口(hwnd)一般很少有父類,我猜測(cè)這里的hWnd = ::GetParent(hWnd)是MFC窗口的父類(如CMainWindow和父類CFrameWnd),而不是Windows窗口(hwnd)的父類

---再次查看代碼:

---剛剛的猜測(cè)錯(cuò)誤,這里就是遍歷Windows窗口的父類

---然后獲取Window窗口對(duì)應(yīng)的MFC窗口映射

---如果MFC窗口能處理這個(gè)消息,就返回TRUE,那么在CWnd::PreTranslateMessage()里面就不需要TranslateMessage和DispatchMessage

---而是通過(guò)MFC的消息映射,用MFC的CFrameWnd類(子類)->PreTranslateMessage(pMsg)來(lái)對(duì)消息進(jìn)行處理

#問(wèn)題:在BOOL CMyApp::InitInstance()中,m_pMainWnd=(CFrameWnd*)new CMainWindow是在堆中分配內(nèi)存,但是沒(méi)有釋放內(nèi)存,容易造成內(nèi)存泄露

---但是窗口關(guān)閉并沒(méi)有照成問(wèn)題Why?CMainWindow自己對(duì)自己進(jìn)行了刪除

---繼承于CWnd,發(fā)現(xiàn)是一個(gè)虛函數(shù),代碼就是:delete this

---在CMainWindows重寫(xiě)PostNcDestroy(),調(diào)用父類的PostNcDestroy(),下斷點(diǎn)

---點(diǎn)擊窗口右上角的關(guān)閉,產(chǎn)生WM_NCDESTROY的消息

---就會(huì)CMainWindows遍歷父子類,對(duì)該消息進(jìn)行處理(emmm我這里沒(méi)辦法進(jìn)入CFrameWnd調(diào)試)

---注意:如果窗口基礎(chǔ)于CWnd,則需要自己去重寫(xiě)PostNcDestroy(),并且執(zhí)行delete this

#總結(jié)

---全局對(duì)象theApp(早于WinMain執(zhí)行),然后進(jìn)入AfxWinMain()

---AfxGetApp()獲取當(dāng)前進(jìn)行的內(nèi)存地址(也是theApp的地址

---AfxWinInit()將AfxWinMain的四個(gè)參數(shù)賦值給theApp的成員變量,創(chuàng)建當(dāng)前應(yīng)用程序主線程

---InitInstance() 被重寫(xiě),其成員變量m_pMainWnd指向new窗口對(duì)象CMainWindow(繼承于CFrameWnd)

---new窗口對(duì)象時(shí),調(diào)用構(gòu)造函數(shù),在里面創(chuàng)建窗口:Create(NULL,"主窗口")

---Create的本質(zhì)是調(diào)用CreateEx(),在里面先創(chuàng)建一個(gè)CREATESTRUCT結(jié)構(gòu)體,用來(lái)存儲(chǔ)需要創(chuàng)建窗口的參數(shù)調(diào)用PreCreateWindow(cs),如果是Windows默認(rèn)的窗口類(窗口類名為NULL),就調(diào)用AfxDeferRegisterClass對(duì)窗口進(jìn)行注冊(cè),并且賦默認(rèn)值。(默認(rèn)類名:_afxWndFrameOrView是一個(gè)char類型的數(shù)組,值為"AfxFrameOrView140sud",是MFC中l(wèi)pszClass的默認(rèn)名

---在AfxDeferRegisterClass中,創(chuàng)建窗口對(duì)象,給窗口對(duì)象設(shè)置:窗口模塊句柄(hInstance),默認(rèn)窗口過(guò)程函數(shù)(如果沒(méi)有消息響應(yīng)函數(shù)),根據(jù)參數(shù)設(shè)置窗口風(fēng)格,然后注冊(cè)窗口

---PreCreateWindow(cs)之后,用AfxHookWindowCreate(this) ,將Windows窗口的消息,在DispatchMessage之后,_AfxCbtFilterHook窗口過(guò)程函數(shù)之前接受消息

---_AfxCbtFilterHook調(diào)用Attach()將Windows窗口句柄(hwnd)和MFC窗口類(CFrameWnd派生類)進(jìn)行綁定,將窗口的消息處理函數(shù)改為afxWndProc

---Attach將hwnd和CFrameWnd進(jìn)行綁定,Windows根據(jù)hwnd找到CFrameWnd

---將映射關(guān)系保存道線程的(theApp)的m_pmapHWNDh成員變量中

---也即是:原來(lái)DispatchMessage后,發(fā)送給窗口過(guò)程函數(shù)的消息,現(xiàn)在發(fā)送給afxWndProc,AfxWndProc得到HWND窗口對(duì)應(yīng)的MFC窗口對(duì)象

---這樣一個(gè)框架類就可以代表一個(gè)窗口,符合面向?qū)ο?/strong>的編程思想

---最后,調(diào)用hWnd = ::CreateWindowEx()創(chuàng)建了窗口(和Win32CreateWindow()一樣)

#窗口的分類

#窗口的創(chuàng)建流程

---模塊和進(jìn)程的區(qū)別:一個(gè)進(jìn)程可以加載多個(gè)模塊,而模塊里面可以是一些代碼

#消息和消息隊(duì)列

---查看AfxWndProc()

---通過(guò)窗口句柄獲取CFrameWnd對(duì)象的指針pFrame

---通過(guò)pFrame指針調(diào)用CFrameWnd的WindowProc函數(shù)進(jìn)行窗口消息的處理

---CFrameWnd的WindowProc是繼承于CWnd::WindowProc

---注意:CObject? > CCmdTarget > CWnd > CFrameWnd

---CObject? > CCmdTarget > CWinThread > CWinApp

------在OnWndMsg循環(huán)搜索本對(duì)象和父類對(duì)象對(duì)應(yīng)的消息映射數(shù)組messageMap,找到對(duì)應(yīng)的_messageEntries中對(duì)應(yīng)的消息響應(yīng)函數(shù)(沒(méi)有就調(diào)用DefWindowProc默認(rèn)處理)

---然后MFC窗口類的消息響應(yīng)函數(shù)對(duì)消息進(jìn)行處理

---如下(注意:消息響應(yīng)函數(shù)的命名要和消息進(jìn)行對(duì)應(yīng))

---MFC的窗口類之間,的消息映射機(jī)制如下

---每個(gè)MFC窗口子父類通過(guò)messageMap關(guān)聯(lián)

---MFC窗口對(duì)應(yīng)一個(gè)_messageEntries結(jié)構(gòu)體(類型記錄鏈表),只能通過(guò)messageMap訪問(wèn),記錄了消息ID和對(duì)應(yīng)的消息響應(yīng)函數(shù)

#在重寫(xiě)InitInstance()窗口創(chuàng)建之后,AfxWinMain()還帶調(diào)用了Run()進(jìn)行消息循環(huán)

---對(duì)于AfxWinMain()來(lái)個(gè)簡(jiǎn)單的總結(jié)

---消息DispatchMessage后,發(fā)送到AfxWndProc()窗口過(guò)程

---AfxWndProc()根據(jù)hWnd和MFC窗口的匹配,調(diào)用MFC窗口的WindowProc()方法

---WindowProc()通過(guò)OnWndMsg遍歷MFC窗口的子父類,找消息響應(yīng)函數(shù),對(duì)消息進(jìn)行處理

#問(wèn)題:

---MFC中的消息循環(huán)機(jī)制Run()有點(diǎn)不明白

---WalkPreTranslateTree()找到Windows窗口對(duì)應(yīng)可以處理消息的MFC窗口,CWinThread::PreTranslateMessage(MSG* pMsg)返回TRUE

---BOOL CWinThread::PumpMessage()返回TRUE,主線程又在消息隊(duì)列里面獲取下一跳消息

---我個(gè)人覺(jué)得Run()存在2個(gè)作用:1.不同的從消息隊(duì)列獲取消息 2.確保消息隊(duì)列獲取的消息,存在的MFC窗口(hwnd對(duì)應(yīng))可以處理它,如果不能處理,或者不存在和消息hwnd對(duì)應(yīng)的MFC窗口類,就直接發(fā)送給hwnd默認(rèn)的窗口函數(shù)處理

【滴水基礎(chǔ)】5.MFC(2)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
四平市| 蚌埠市| 黄龙县| 朔州市| 白水县| 吴江市| 出国| 得荣县| 东乌珠穆沁旗| 宁夏| 临夏市| 客服| 盈江县| 克东县| 尖扎县| 临高县| 炉霍县| 寿光市| 大连市| 清镇市| 浙江省| 余江县| 平顺县| 永春县| 商都县| 沈阳市| 岳普湖县| 盐城市| 嘉祥县| 海淀区| 澄江县| 毕节市| 文登市| 通渭县| 阿克| 永顺县| 揭东县| 肇源县| 新巴尔虎右旗| 纳雍县| 察雅县|