国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【MFC】06.MFC第二大機(jī)制:窗口創(chuàng)建機(jī)制-筆記

這篇具有很好參考價(jià)值的文章主要介紹了【MFC】06.MFC第二大機(jī)制:窗口創(chuàng)建機(jī)制-筆記。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

接上文【MFC】05.MFC第一大機(jī)制:程序啟動(dòng)機(jī)制-筆記,這一篇文章來帶領(lǐng)大家逆向分析MFC第二大機(jī)制:窗口創(chuàng)建機(jī)制的源碼。
我們知道,在Win32編程中,如果我們要?jiǎng)?chuàng)建一個(gè)窗口,基本步驟為:

  1. 注冊(cè)窗口
  2. 創(chuàng)建一個(gè)窗口,必須要給一個(gè)類名稱
  3. 消息處理回調(diào)函數(shù)

那么MFC的窗口創(chuàng)建機(jī)制又是怎樣的呢?我們來回溯一下MFC源碼:

首先,我們繼續(xù)用上文中創(chuàng)建的MFC程序:

#include <afxwin.h>

//實(shí)現(xiàn)我們自己的框架類
class CMyFrameWnd :public CFrameWnd {
public:
};

//實(shí)現(xiàn)我們自己的應(yīng)用程序類
class CMyApp :public CWinApp {
public:
	CMyApp() {};

	//重寫虛函數(shù)
	virtual BOOL InitInstance() {
		CMyFrameWnd* pFrame = new CMyFrameWnd;
		pFrame->Create(NULL, L"FirstMFC");
		m_pMainWnd = pFrame;
		pFrame->ShowWindow(SW_SHOW);
		pFrame->UpdateWindow();
		return TRUE;
	}
};

CMyApp theApp;

不難猜到,創(chuàng)建窗口的代碼在這:pFrame->Create(NULL, L"FirstMFC");我們就在這行代碼上下斷點(diǎn),跟過去:

我們知道我們重寫的的InitInstance函數(shù)在WinMian函數(shù)轉(zhuǎn)發(fā)的AfxwWimMian函數(shù)中會(huì)被調(diào)用:

這里給的參數(shù),第一個(gè)NULL是lpszClassName(窗口類名),第二個(gè)參數(shù)是lpszWindowName(應(yīng)用程序類名),但是我們了解Win32編程,我們知道如果想要?jiǎng)?chuàng)建窗口或者是注冊(cè)窗口,都必須要窗口類名,但是這里給的是NULL,為什么還是能夠正常執(zhí)行過去呢?

virtual BOOL InitInstance(){
  	CMyFrameWnd* pFrame = new CMyFrameWnd;
  	//Create函數(shù)是框架類的方法:
  	//我們知道Create方法的參數(shù)肯定不止倆,我們跟過去之后,發(fā)現(xiàn)其他參數(shù)是有默認(rèn)參數(shù)的
		pFrame->Create(NULL, L"FirstMFC")
		{
		  //進(jìn)入函數(shù)第一件事:判斷是否包含菜單,如果包含菜單,則加載菜單
		  HMENU hMenu = NULL;
    	if (lpszMenuName != NULL)
    	{
    		HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, ATL_RT_MENU);
    		if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)
    		{
    			TRACE(traceAppMsg, 0, "Warning: failed to load menu for CFrameWnd.\n");
    			PostNcDestroy();
    			return FALSE;
    		}
	    }
	    
	    	m_strTitle = lpszWindowName;    // save title for later
        
        //這里的代碼很明顯是創(chuàng)建窗口了,但是沒有窗口類名,怎么能創(chuàng)建窗口呢?我們跟進(jìn)去看看:
        //這里由于其他參數(shù)我們不關(guān)注,這里只留下窗口類名
        //這里源代碼函數(shù)實(shí)現(xiàn)實(shí)在if語(yǔ)句的條件中執(zhí)行的,這里直接拉出來
      	CreateEx( lpszClassName, lpszWindowName,...)
      	{
      	    //可以看到在這里有斷言:
      	  	ASSERT(lpszClassName == NULL || AfxIsValidString(lpszClassName) ||
          		AfxIsValidAtom(lpszClassName));
          	ENSURE_ARG(lpszWindowName == NULL || AfxIsValidString(lpszWindowName));
          
            //這里是創(chuàng)建窗口所需要的類:
          	CREATESTRUCT cs;
          	cs.dwExStyle = dwExStyle;
          	cs.lpszClass = lpszClassName;
          	cs.lpszName = lpszWindowName;
          	cs.style = dwStyle;
          	cs.x = x;
          	cs.y = y;
          	cs.cx = nWidth;
          	cs.cy = nHeight;
          	cs.hwndParent = hWndParent;
          	cs.hMenu = nIDorHMenu;
          	cs.hInstance = AfxGetInstanceHandle();
          	cs.lpCreateParams = lpParam;
          	
          	//這里隱含的this指針:框架類窗口
          	PreCreateWindow(cs){
          	  //跟進(jìn)去函數(shù)也能發(fā)現(xiàn)是框架類窗口的方法
          	  BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
              {
              	if (cs.lpszClass == NULL)
              	{
              	  //發(fā)現(xiàn)這里有一個(gè)貌似MFC注冊(cè)窗口的函數(shù):跟進(jìn)去看看
              		VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)){
              		  	//這些是所需要的類,相信大家都很熟悉了
              		  	WNDCLASS wndcls;
                    	memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults
                    	wndcls.lpfnWndProc = DefWindowProc;
                    	wndcls.hInstance = AfxGetInstanceHandle();
                    	wndcls.hCursor = afxData.hcurArrow;
                    	
                    	//接下來發(fā)現(xiàn)了好多類似的代碼,應(yīng)該是判斷一些東西,我們的代碼進(jìn)入了這個(gè)if語(yǔ)句,我們就跟進(jìn)去
                    	if (fToRegister & AFX_WNDFRAMEORVIEW_REG)
                    	{
                    		//這里是對(duì)wndcls做一些賦值操作
                    		wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
                    		wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
                    		//代碼跟到這里,應(yīng)該是注冊(cè)窗口了,因?yàn)榘勺?cè)窗口所需要的類傳進(jìn)去了,為了以防萬(wàn)一,我們跟進(jìn)去看看:
                    		if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME)){
                    		    //代碼前部分做了一些賦值操作,加載圖標(biāo)
                    		    //我們跟到這個(gè)函數(shù)中看看注冊(cè)操作:
                          	return AfxRegisterClass(pWndCls){
                          	  	WNDCLASS wndcls;
                          	  	//這里的GetClassInfo是判斷窗口是否已經(jīng)注冊(cè)過
                                	GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,&wndcls)
                                  //在這里發(fā)現(xiàn)了Win32API:注冊(cè)窗口
                                	if (!RegisterClass(lpWndClass))
                          	}
                    		}
                    	}
                    	//在注冊(cè)玩窗口后,發(fā)現(xiàn)了這段代碼
                    	//這里的_afxWndFrameOrView是一個(gè)宏或者數(shù)組,跟過去看看,發(fā)現(xiàn)是個(gè)數(shù)組
                    	//跟到最后,發(fā)現(xiàn)是FrameOrView
                    	cs.lpszClass = _afxWndFrameOrView;
              		}
              	}
              	
              	...
              	
              	return TRUE;
              }
          	}
      	}
      	  //在創(chuàng)建窗口之前,發(fā)現(xiàn)埋下了一個(gè)鉤子
      		AfxHookWindowCreate(this){
        		  void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
            {
              //MFC的第三個(gè)全局變量
            	_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
            	
            	if (pThreadState->m_pWndInit == pWnd)
            		return;
            		//這里是埋下了一個(gè)創(chuàng)建窗口的消息鉤子
            	pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
            		//如果失敗的話,拋出異常
            		if (pThreadState->m_hHookOldCbtFilter == NULL)
            			AfxThrowMemoryException();
            	}
            	//這里保存了我們的框架類窗口對(duì)象
            	pThreadState->m_pWndInit = pWnd;
            }
      		}
      		//發(fā)現(xiàn)這里是創(chuàng)建窗口
        	HWND hWnd = CreateWindowEx(cs.dwExStyle, cs.lpszClass,
        			cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
        			cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
		}
}

觸發(fā)的鉤子函數(shù)
LRESULT CALLBACK _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
{
//MFC第三個(gè)全局變量的地址
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
//取出結(jié)構(gòu)體參數(shù)
LPCREATESTRUCT lpcs = ((LPCBT_CREATEWND)lParam)->lpcs;
//多態(tài) 父類指針 指向子類
CWnd* pWndInit = pThreadState->m_pWndInit

//創(chuàng)建的窗口句柄
HWND hWnd = (HWND)wParam;

//窗口句柄傳入了進(jìn)去
//內(nèi)部this指針是我們的對(duì)象
pWndInit->Attach(hWnd);
{
    //MAP對(duì)象
    CHandleMap* pMap = afxMapHWND(TRUE); 
    {
        //MFC 第二個(gè)全局變量 線程模塊狀態(tài) 
        AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
        //把映射類對(duì)象 保存到了 第二個(gè)全局變量里面
        pState->m_pmapHWND = new CHandleMap
        return pState->m_pmapHWND;
    }
    
    //內(nèi)部this指針是誰(shuí) pMap映射類對(duì)象
    pMap->SetPermanent(this->m_hWnd = hWndNew, 框架類對(duì)象);
    {
        inline void CHandleMap::SetPermanent(HANDLE h, CObject* permOb)
        {
            //pMap映射類對(duì)象
            this->m_permanentMap[窗口句柄] = 框架類對(duì)象 pFrame;
            //stl map  map[key] = val
        }
    }
    
    WNDPROC afxWndProc = AfxGetAfxWndProc();
    oldWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,(DWORD_PTR)afxWndProc);
}

LRESULT lResult = CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,wParam, lParam);

}

//真正的窗口過程處理函數(shù)
AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
{
CHandleMap* pMap = afxMapHWND();
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
pState->m_pmapHWND
}

    return (CObject*)m_permanentMap.GetValueAt((LPVOID)h);        
}

AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam)
{
    //父類指針 指向了子類 
    lResult = pWnd->WindowProc(nMsg, wParam, lParam);
}

}文章來源地址http://www.zghlxwxcb.cn/news/detail-632385.html

到了這里,關(guān)于【MFC】06.MFC第二大機(jī)制:窗口創(chuàng)建機(jī)制-筆記的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【MFC】07.MFC六大機(jī)制:消息映射-筆記

    本專欄上兩篇文章分別介紹了【MFC】05.MFC第一大機(jī)制:程序啟動(dòng)機(jī)制和【MFC】06.MFC第二大機(jī)制:窗口創(chuàng)建機(jī)制,這篇文章來為大家介紹MFC的第三大機(jī)制:消息映射 typfd要實(shí)現(xiàn)消息映射,必須滿足的三個(gè)條件: 類必須繼承于CmdTargert 類必須聲明重定義 DECLARE_MESSAGE_MAP 類外必須實(shí)

    2024年02月13日
    瀏覽(24)
  • 【MFC】07.MFC第三大機(jī)制:消息映射-筆記

    本專欄上兩篇文章分別介紹了【MFC】05.MFC第一大機(jī)制:程序啟動(dòng)機(jī)制和【MFC】06.MFC第二大機(jī)制:窗口創(chuàng)建機(jī)制,這篇文章來為大家介紹MFC的第三大機(jī)制:消息映射 typfd要實(shí)現(xiàn)消息映射,必須滿足的三個(gè)條件: 類必須繼承于CmdTargert 類必須聲明重定義 DECLARE_MESSAGE_MAP 類外必須實(shí)

    2024年02月14日
    瀏覽(15)
  • MFC 非線程創(chuàng)建模態(tài)化窗口 實(shí)現(xiàn)工具欄拓展

    MFC 非線程創(chuàng)建模態(tài)化窗口 實(shí)現(xiàn)工具欄拓展

    1.1 在Dlg.h文件中聲明變量和定義資源ID 1.2 在資源視圖中導(dǎo)入Bitmap資源圖片 可以在右擊資源符號(hào)中查看具體ID值 1.3 在Dlg.cpp文件中的OnInitDialog()方法中導(dǎo)入Bitmap與按鈕ID 1.4 開啟鼠標(biāo)??啃畔⑻崾?先在Dlg.h中增加函數(shù)聲明 再Dlg.cpp中實(shí)現(xiàn) 增加消息映射宏開啟提示 1.5 效果呈現(xiàn) 2.

    2024年02月10日
    瀏覽(17)
  • MFC 隱藏窗口

    親測(cè)能用 改變主窗體的創(chuàng)建方式 將?C***App::InitInstance() 函數(shù)中的代碼 替換為

    2024年02月11日
    瀏覽(18)
  • mfc 浮動(dòng)窗口

    mfc 浮動(dòng)窗口

    參考 MFC模擬360懸浮窗加速球窗口

    2024年02月09日
    瀏覽(25)
  • MFC多文檔如何分割窗口

    MFC多文檔如何分割窗口

    本文記錄如何在MFC多文件中分割窗口并實(shí)現(xiàn)窗口之間的數(shù)據(jù)傳遞 1、在ChildFrame中定義一個(gè)分割嵌入一個(gè)CSplitterWnd成員變量。 2、創(chuàng)建兩個(gè)對(duì)話框, 設(shè)置對(duì)話框的屬性 :將 ‘樣式’ 設(shè)置為 ‘下層’; 禁止使用 標(biāo)題欄; 邊框選擇‘ 調(diào)整大小 ’;其他格式暫時(shí)都不設(shè)置; ? ? ?

    2024年02月06日
    瀏覽(23)
  • MFC 第二部分 : 窗口類成員接口

    所有窗口類的基類:類 CWnd,封裝了 Windows 窗口句柄 HWND。 成員函數(shù) DestroyWindow 可以消毀 Windows 窗口,而不需要消毀 CWnd 對(duì)象。 m_hWnd 與該 CWnd 對(duì)象相關(guān)聯(lián)的 Windows 窗口句柄(HWND); 窗口大小和位置 GetWindowRgn 獲得窗口的窗口區(qū)域的拷貝 SetWindowRgn 設(shè)置窗口區(qū)域 IsIconic 判斷窗口是

    2024年02月06日
    瀏覽(56)
  • MFC窗口透明化以及透明穿透

    MFC窗口透明化以及透明穿透

    MFC編程時(shí),有時(shí)候我們需要實(shí)現(xiàn)窗口透明化,可以通過SetLayeredWindowAttributes設(shè)置窗口透明色和透明度來實(shí)現(xiàn)窗口透明化。而要使窗口擁有透明效果,前提是窗口要有WS_EX_LAYERED擴(kuò)展屬性,需用SetWindowLong設(shè)置窗口支持拓展風(fēng)格。 一、窗口透明化說明 1.窗口透明化有三種模式: 第一

    2024年02月09日
    瀏覽(17)
  • 微軟MFC技術(shù)運(yùn)行機(jī)制

    微軟MFC技術(shù)運(yùn)行機(jī)制

    我是荔園微風(fēng),作為一名在IT界整整25年的老兵,今天總結(jié)一下微軟MFC技術(shù)運(yùn)行機(jī)制。 很多初學(xué)者誤以為VC++開發(fā)必須使用MFC,其實(shí)不一定的。MFC的使用只能是提高程序在某些情況下的開發(fā)效率,而不能替代整個(gè)Win32程序設(shè)計(jì)。我認(rèn)為我們有必要再來好好講講MFC的本質(zhì)、MFC中的

    2024年02月08日
    瀏覽(18)
  • MFC 序列化機(jī)制

    MFC 序列化機(jī)制

    目錄 文件操作相關(guān)類 序列化機(jī)制相關(guān)類 序列化機(jī)制使用 序列化機(jī)制執(zhí)行過程 序列化類對(duì)象 CFile:文件操作類,封裝了關(guān)于文件讀寫等操作,常見的方法: CFile::Open:打開或者創(chuàng)建文件 CFile::Write/Read:寫/讀文件 CFile::Close:關(guān)閉文件 CFile::SeekToBegin/SeekToEnd/Seek:從 開始/結(jié)束

    2024年01月20日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包