• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            溫故而知新,學(xué)習(xí)MFC框架如何創(chuàng)建的過程收藏

             

            下面我們跟蹤一個(gè)MFC MDI的應(yīng)用程序,來溫習(xí)或?qū)W習(xí)一下。

            使用AppWizard創(chuàng)建一個(gè)MDI應(yīng)用程序,我創(chuàng)建的應(yīng)用程序叫MDITest,這樣MFC生成了如下的類:

            類名

            作用

            CMDITestApp

            派生于CWinApp的應(yīng)用程序類。

            CMainFrame

            派生于CMDIFrameWnd的MDI框架窗口類。

            CMDITestDoc

            派生于CDocument的文檔類。

            CChildFrame

            派生于CMDIChildWnd的MDI子窗口類。

            CMDITestView

            派生于CView的文檔顯示類。

             

            在運(yùn)行時(shí)刻,CMainFrame, CChildFrame, CMDITestView的窗口關(guān)系如下面的表格示出:

            CMainFrame

            (Menu, Toolbar …)

            MDIClient

             

            CChildFrame

            CMDITestView

               pDocument = *CMDITestDoc   (帶有文檔的指針)

             

             

             

             

             

            [StatusBar]

            其中,最外層的是頂層窗口CMainFrame,里面包含一個(gè)MDIClient窗口。CChildFrame做為子窗口包含于MDIClient中(可以包含多個(gè)),CChildFrame里面則是真實(shí)的文檔表示窗口CMDITestView了。

             

            我們從這里開始:

            // CMDITestApp 初始化

            BOOL CMDITestApp::InitInstance()

             

            做為CWinApp的派生類,通常需要重載InitInstance(), ExitInstance()兩個(gè)函數(shù),以完成應(yīng)用的初始化和退出。我們現(xiàn)在關(guān)心InitInstance中關(guān)于文檔模板、窗口處理的部分,而忽略掉一些CommonControl, OLE初始化部分。

             

            整個(gè)InitInstance代碼如下:

            BOOL CMDITestApp::InitInstance()

            {

                 InitCommonControls();       // 這里刪減了大量注釋和錯(cuò)誤處理

                 CWinApp::InitInstance();

                 AfxOleInit();

                 AfxEnableControlContainer();

                 SetRegistryKey(_T("應(yīng)用程序向?qū)傻谋镜貞?yīng)用程序"));

                 LoadStdProfileSettings(4);  // 加載標(biāo)準(zhǔn) INI 文件選項(xiàng)(包括 MRU)

             

                 TRACE("Before CMultiDocTemplate\n");

                 // 注冊應(yīng)用程序的文檔模板。文檔模板

                 // 將用作文檔、框架窗口和視圖之間的連接

                 CMultiDocTemplate* pDocTemplate;

                 pDocTemplate = new CMultiDocTemplate(IDR_MDITestTYPE,

                     RUNTIME_CLASS(CMDITestDoc),

                     RUNTIME_CLASS(CChildFrame), // 自定義 MDI 子框架

                     RUNTIME_CLASS(CMDITestView));

                 if (!pDocTemplate)

                     return FALSE;

                 TRACE("Before AddDocTemplate\n");

                 AddDocTemplate(pDocTemplate);

             

                 // 創(chuàng)建主 MDI 框架窗口

                 TRACE("Before new CMainFrame\n");

                 CMainFrame* pMainFrame = new CMainFrame;

                 TRACE("Before pMainFrame->LoadFrame\n");

                 if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))

                     return FALSE;

                 m_pMainWnd = pMainFrame;

             

                 TRACE("Before ParseCommandLine\n");

                 CCommandLineInfo cmdInfo;

                 ParseCommandLine(cmdInfo);

             

                 // 調(diào)度在命令行中指定的命令。如果

                 // 用 /RegServer、/Register、/Unregserver 或 /Unregister 啟動應(yīng)用程序,則返回 FALSE。

                 TRACE("Before ProcessShellCommand\n");

                 if (!ProcessShellCommand(cmdInfo))

                     return FALSE;

             

                 TRACE("Before pMainFrame->ShowWindow\n");

                 // 主窗口已初始化,因此顯示它并對其進(jìn)行更新

                 pMainFrame->ShowWindow(m_nCmdShow);

                 TRACE("Before pMainFrame->UpdateWindow\n");

                 pMainFrame->UpdateWindow();

                 return TRUE;

            }

             

            為了研究整個(gè)創(chuàng)建過程,我在其中添加了一些TRACE來跟蹤創(chuàng)建順序。

             

            忽略掉開始的亂七八糟的初始化,從CMultiDocTemplate開始:

                 CMultiDocTemplate* pDocTemplate = new CMultiDocTemplate(IDR_MDITestTYPE,

                     RUNTIME_CLASS(CMDITestDoc),

                     RUNTIME_CLASS(CChildFrame), // 自定義 MDI 子框架

                     RUNTIME_CLASS(CMDITestView));

                 AddDocTemplate(pDocTemplate);

            (作了一點(diǎn)點(diǎn)簡化)

            這里首先創(chuàng)建了一個(gè)CMultiDocTemplate —— 文檔模板,文檔模板包括的三個(gè)運(yùn)行時(shí)刻類信息:Document – CMDITestDoc, FrameWnd – CChildFrame, View – CMDITestView。

            然后通過AddDocTemplate函數(shù)將新創(chuàng)建的文檔模板添加到模板管理器之中(我們以后再研究模板管理器)。

             

            然后創(chuàng)建主框架窗口CMainFrame:

                 CMainFrame* pMainFrame = new CMainFrame;

                 if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))

                     return FALSE;

             

            其中,需要研究的是LoadFrame的實(shí)現(xiàn),以及里面都做了些什么。我們稍后研究。

             

            處理命令行,在這里第一個(gè)空文檔被建立出來:

                 CCommandLineInfo cmdInfo;

                 ParseCommandLine(cmdInfo);

             

                 // 調(diào)度在命令行中指定的命令。如果用 /RegServer、/Register、/Unregserver 或 /Unregister 啟動應(yīng)用程序,則返回 FALSE。

                 if (!ProcessShellCommand(cmdInfo))               // ß 這里創(chuàng)建出初始空文檔

                     return FALSE;

             

            我們一會會重點(diǎn)研究ProcessShellCommand。

             

            最后,顯示主窗口:

                 pMainFrame->ShowWindow(m_nCmdShow);

                 pMainFrame->UpdateWindow();

             

            至此,WinApp::InitInstance()完成了自己的工作。

             

            上面遺留了三個(gè)待研究的分支,讓我們現(xiàn)在去研究它們:

            1、  CDocTemplate

            2、  CFrameWnd::LoadFrame

            3、  CWnd::ProcessShellCommand

             

             

             

            研究CDocTemplate

             

            我們的例子中是構(gòu)造了一個(gè)CMultiDocTemplate,它是從CDocTemplate派生而來,所以我們主要研究CDocTemplate。

            CDocTemplate的幾個(gè)關(guān)鍵屬性列表如下:

                 CRuntimeClass* m_pDocClass;         // class for creating new documents

                 CRuntimeClass* m_pFrameClass;       // class for creating new frames

                 CRuntimeClass* m_pViewClass;        // class for creating new views

             

            其中:

            m_pDocClass

            表示文檔類類型,在此例子中就是CMDITestDoc

            m_pFrameClass

            表示容納View窗口的框架窗口類類型,此例中為CChildFrame

            m_pViewClass

            表示顯示文檔的View視類類型,此例中為CMDITestView

             

            我們可以這樣認(rèn)為,CDocTemplate用于描述Frame-View-Doc的關(guān)系。當(dāng)然它還有一大堆別的屬性,我們暫時(shí)先忽略。

             

            一會還會看到CDocTemplate的創(chuàng)建文檔、框架、視的過程,放在ProcessShellCommand中研究。

             

             

            研究LoadFrame

             

            讓我們繼續(xù)研究CFrameWnd::LoadFrame是怎么運(yùn)作的。使用的方法是跟蹤進(jìn)入。。。

            BOOL CMDIFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,

                 CWnd* pParentWnd, CCreateContext* pContext)

            {

                 // 調(diào)用基類 CFrameWnd 的 LoadFrame, pContext 在創(chuàng)建主窗口時(shí) = NULL

                 //   pParentWnd = NULL

                 if (!CFrameWnd::LoadFrame(nIDResource, dwDefaultStyle,

                   pParentWnd, pContext))

                     return FALSE;

             

                 // save menu to use when no active MDI child window is present

                 ASSERT(m_hWnd != NULL);

                 // 主窗口帶有菜單,所以。。。

                 m_hMenuDefault = ::GetMenu(m_hWnd);

                 if (m_hMenuDefault == NULL)

                     TRACE(traceAppMsg, 0, "Warning: CMDIFrameWnd without a default menu.\n");

                 return TRUE;

            }

            注意,我們的MDITest Application的主窗口CMainFrame是從CMDIFrameWnd派生的,所以進(jìn)入到這里,參考代碼中紅色的注釋部分。繼續(xù)跟蹤進(jìn)入CFrameWnd::LoadFrame。

             

            BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,

                 CWnd* pParentWnd, CCreateContext* pContext)

            {

                 // only do this once

                 ASSERT_VALID_IDR(nIDResource);    // nIDResource = 128, IDR_MAINFRAME

                 ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);

             

                 m_nIDHelp = nIDResource;    // ID for help context (+HID_BASE_RESOURCE)

             

                 CString strFullString;

                 if (strFullString.LoadString(nIDResource))  // = “MDITest”

                     AfxExtractSubString(m_strTitle, strFullString, 0);    // 取得第一個(gè)子串

             

                 VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

             

                 // attempt to create the window

                 // GetIconWndClass 會調(diào)用 virtual PreCreateWindow 函數(shù),別處也會調(diào)用,從而

                 // 使得子類的PreCreateWindow 將被調(diào)用多次

                 LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);

                 CString strTitle = m_strTitle;

                 // 調(diào)用 CFrameWnd::Create() 實(shí)際創(chuàng)建出窗口。

                 // 注意:在這里將給 CMainFrame 發(fā)送 WM_CREATE 等多個(gè)消息。觸發(fā) CMainFrame 的

                 //   OnCreate 處理等。

                 if (!Create(lpszClass, strTitle, dwDefaultStyle, rectDefault,

                   pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))

                 {

                     return FALSE;   // will self destruct on failure normally

                 }

             

                 // save the default menu handle, 好像 CMDIFrameWnd 也保存了一次?

                 ASSERT(m_hWnd != NULL);

                 m_hMenuDefault = ::GetMenu(m_hWnd);

             

                 // load accelerator resource

                 LoadAccelTable(MAKEINTRESOURCE(nIDResource));

             

                 // WM_INITIALUPDATE 是 MFC 發(fā)明的消息,參見后面的說明。

                 if (pContext == NULL)   // send initial update

                     SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);

             

                 return TRUE;

            }

             

            以下是從TN024: MFC-Defined Messages And Resources中抽取的部分說明:

            WM_INITIALUPDATE

            This message is sent by the document template to all descendants of a frame window when it is safe for them to do their initial update. It maps to a call to CView::OnInitialUpdate but can be used in other CWnd-derived classes for other one-shot updating.

            wParam

            Not used (0)

            lParam

            Not used (0)

            returns

            Not used (0)

             

            歸納一下,LoadFrame中進(jìn)行了如下事情:

            1、  注冊窗口類(AfxDeferRegisterClass)

            2、  實(shí)際創(chuàng)建窗口(Create)

            3、  處理菜單、快捷鍵,發(fā)送WM_INITIALUPDATE消息給所有子窗口。實(shí)際將在CView中處理此消息。(例如:在ToolBar上面放一個(gè)FormView,可能就能收到這個(gè)消息并處利?)

             

            至此,CMainFrame已經(jīng)成功創(chuàng)建,菜單已經(jīng)裝載,工具條、狀態(tài)行等已經(jīng)在CMainFrame::OnCreate中創(chuàng)建。讓我們接著研究第一個(gè)子窗口是怎么被創(chuàng)建出來的,該過程和CMainFrame::LoadFrame比起來就不那么直接了。

             

             

            研究CWnd::ProcessShellCommand

             

            第一個(gè)MDI子窗口是從這里面建立出來的,這實(shí)在是缺乏直觀性。不過MFC就是這樣,沒辦法。

            BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo)

            {

                 BOOL bResult = TRUE;

                 switch (rCmdInfo.m_nShellCommand)

                 {

                 case CCommandLineInfo::FileNew:

                     if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL))      // 關(guān)鍵是這里

                          OnFileNew();

                     if (m_pMainWnd == NULL)

                          bResult = FALSE;

                     break;

             

                 case CCommandLineInfo::FileOpen:                // 忽略

                 case CCommandLineInfo::FilePrintTo:            // 忽略

                 case CCommandLineInfo::FilePrint:

                 case CCommandLineInfo::FileDDE:

                 case CCommandLineInfo::AppRegister:

                 case CCommandLineInfo::AppUnregister:

                 }

                 return bResult;

            }

            進(jìn)入到ProcessShellCommand,要處理很多種不同命令,我們忽略其它命令,單獨(dú)看FileNew部分。

            注意:實(shí)際進(jìn)入到了AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)之中。

             

            AfxGetApp()實(shí)際返回了CMDITestApp的唯一實(shí)例,它從CWinApp – CWinThread – CCmdTarget – CObject 派生而來。我們沒有重載OnCmdMsg,所以進(jìn)入到CCmdTarget的OnCmdMsg處理中。為了研究,我們刪減了一些代碼。

            BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode, void* pExtra,

                 AFX_CMDHANDLERINFO* pHandlerInfo)

            {

                 // 這里刪減了一些代碼

                 // determine the message number and code (packed into nCode)

                 const AFX_MSGMAP* pMessageMap;

                 const AFX_MSGMAP_ENTRY* lpEntry;

                 UINT nMsg = 0;

                 // 這里刪減了一些代碼,處理后 nMsg = WM_COMMAND

                 // 為了簡化,刪減了一些斷言等。以下循環(huán)用于查找處理此消息的入口。

                 for (pMessageMap = GetMessageMap(); pMessageMap->pfnGetBaseMap != NULL;

                   pMessageMap = (*pMessageMap->pfnGetBaseMap)())

                 {

                     lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries, nMsg, nCode, nID);

                     if (lpEntry != NULL)

                     {

                          // 找到了消息處理項(xiàng)入口,分發(fā)此消息。

                          return _AfxDispatchCmdMsg(this, nID, nCode,

                               lpEntry->pfn, pExtra, lpEntry->nSig, pHandlerInfo);

                     }

                 }

                 return FALSE;   // 未找到則不處理

            }

            最終MFC很愉快地找到了一個(gè)入口項(xiàng),       CWinApp::OnFileNew(void)       要處理這個(gè)消息。繼續(xù)進(jìn)入到_AfxDispatchCmdMsg中去看看。

             

            AFX_STATIC BOOL AFXAPI _AfxDispatchCmdMsg(CCmdTarget* pTarget, UINT nID, int nCode,

                 AFX_PMSG pfn, void* pExtra, UINT_PTR nSig, AFX_CMDHANDLERINFO* pHandlerInfo)

                     // return TRUE to stop routing

            {

                 union MessageMapFunctions mmf;

                 mmf.pfn = pfn;

                 BOOL bResult = TRUE; // default is ok

             

                 if (pHandlerInfo != NULL)

                 {

                     // just fill in the information, don't do it

                     pHandlerInfo->pTarget = pTarget;

                     pHandlerInfo->pmf = mmf.pfn;

                     return TRUE;

                 }

             

                 switch (nSig)

                 {

                 case AfxSigCmd_v:

                     // normal command or control notification

                     ASSERT(CN_COMMAND == 0);        // CN_COMMAND same as BN_CLICKED

                     ASSERT(pExtra == NULL);

                     (pTarget->*mmf.pfnCmd_v_v)();         // ß 實(shí)際調(diào)用 pTarget 指向的這個(gè)成員函數(shù)

                     break;

                 // 下面還有大量的多種 AfxSigCmd_xxx,忽略掉它們。

                 default:    // illegal

                     ASSERT(FALSE); return 0; break;

                 }

                 return bResult;

            }

             

            其中 (pTarget->*mmf.pfn_Cmd_v_v)() 對CWinApp::OnFileNew() 產(chǎn)生調(diào)用,pTarget = CMDITestApp類實(shí)例。調(diào)用進(jìn)入如下:

             

            void CWinApp::OnFileNew()

            {

                 if (m_pDocManager != NULL)

                     m_pDocManager->OnFileNew();

            }

             

            進(jìn)入進(jìn)入到CDocManager::OnFileNew()

             

            void CDocManager::OnFileNew()

            {

                 if (m_templateList.IsEmpty())

                      // 提示沒有模板并返回

                 CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();    // 第一個(gè)

                 if (m_templateList.GetCount() > 1)

                      // 彈出一個(gè)對話框(很難看的)提示用戶選擇一個(gè)文檔模板

             

                 // 在這個(gè)例子里面,pTemplate 就是 CMDITestApp::InitInstance() 里面創(chuàng)建的那個(gè)模板

                 pTemplate->OpenDocumentFile(NULL);

            }

             

            在進(jìn)入CMultiDocTemplate::OpenDocumentFile之前,我觀察了一下調(diào)用堆棧,結(jié)果如下:

            >   mfc71d.dll!CDocManager::OnFileNew()  行852  C++

                mfc71d.dll!CWinApp::OnFileNew()  行25   C++

                mfc71d.dll!_AfxDispatchCmdMsg(CCmdTarget * pTarget=0x0042cae8, unsigned int nID=57600, int nCode=0, void (void)* pfn=0x0041153c, void * pExtra=0x00000000, unsigned int nSig=53, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000)  行89   C++

                mfc71d.dll!CCmdTarget::OnCmdMsg(unsigned int nID=57600, int nCode=0, void * pExtra=0x00000000, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000)  行396 + 0x27    C++

                mfc71d.dll!CWinApp::ProcessShellCommand(CCommandLineInfo & rCmdInfo={...})  行27 + 0x1e C++

                MDITest.exe!CMDITestApp::InitInstance()  行101 + 0xc    C++

            希望我還沒有迷路:)

             

             

            CMultiDocTemplate::OpenDocumentFile 又是很多很多代碼,讓我們選擇一些。

            CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,

                 BOOL bMakeVisible)

            {

                 // 以下代碼刪減了驗(yàn)證、斷言部分

                 CDocument* pDocument = CreateNewDocument();              // 創(chuàng)建文檔對象

                 CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);    // 創(chuàng)建框架窗口

             

                 if (lpszPathName == NULL)

                 {

                     pDocument->OnNewDocument();           // 初始化文檔

                 }

                 else

                      // 打開已有文檔

             

                 InitialUpdateFrame(pFrame, pDocument, bMakeVisible);

                 return pDocument;

            }

             

             

            看一看CreateNewDocument()

            CDocument* CDocTemplate::CreateNewDocument()

            {

                 // default implementation constructs one from CRuntimeClass

                 if (m_pDocClass == NULL)

                      // 錯(cuò)誤提示啦

                 // CRuntimeClass* m_pDocClass -> CreateObject 實(shí)例化文檔類。

                 // 在此例子中既是 CMDITestDoc

                 CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();

                 AddDocument(pDocument);      // 添加到模板里的文檔列表,MultiDocTemplate 保存此一文檔

                 return pDocument;

            }

             

             

            CMDITestDoc有如下的定義,僅能從CRuntimeClass里面創(chuàng)建的。

            class CMDITestDoc : public CDocument

            {

            protected: // 僅從序列化創(chuàng)建

                 CMDITestDoc();               // 被保護(hù)的構(gòu)造函數(shù)

                 DECLARE_DYNCREATE(CMDITestDoc)             // 支持從 CRuntimeClass 信息中創(chuàng)建。

             

             

            再接著進(jìn)行CreateNewFrame。

            CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)

            {

                 // create a frame wired to the specified document

                 CCreateContext context;           // 這個(gè) CreateContext 傳遞到 LoadFrame 中

                 context.m_pCurrentFrame = pOther;         // 此例中 = NULL

                 context.m_pCurrentDoc = pDoc;              // = 剛才創(chuàng)建的文檔

                 context.m_pNewViewClass = m_pViewClass;   // 顯示此文檔的視類的類型

                 context.m_pNewDocTemplate = this;

             

                 if (m_pFrameClass == NULL)

                      // 提示錯(cuò)誤并返回

                 // 利用 CRuntimeClass 信息創(chuàng)建框架窗口對象,此例中為 CChildFrame

                 CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();

             

                 // 這里,我們又看到了 LoadFrame , 參考前面的 LoadFrame 吧

                 // 在這里面,View 窗口也被產(chǎn)生出來。參考 TRACE 輸出。

                 pFrame->LoadFrame(m_nIDResource,

                          WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,   // default frame styles

                          NULL, &context);

                 return pFrame;

            }

             

             

            LoadFrame之后View窗口將被創(chuàng)建出來,接著進(jìn)入到CMDITestDoc::OnNewDocument中,現(xiàn)在僅僅是一個(gè)空的函數(shù),沒有特定代碼。

            BOOL CMDITestDoc::OnNewDocument()

            {

               TRACE("CMDITestDoc::OnNewDocument() entry\n");

                 if (!CDocument::OnNewDocument())

                     return FALSE;

             

                 // TODO: 在此添加重新初始化代碼

                 // (SDI 文檔將重用該文檔)

             

                 return TRUE;

            }

             

            最后是CDocTemplate::InitialUpdateFrame,這里面主要是激活新建的框架、文檔、視,看得挺頭疼的。

            void CDocTemplate::InitialUpdateFrame(CFrameWnd* pFrame, CDocument* pDoc,

                 BOOL bMakeVisible)

            {

                 // just delagate to implementation in CFrameWnd

                 pFrame->InitialUpdateFrame(pDoc, bMakeVisible);

            }

             

            現(xiàn)在,文檔、框架窗口、視窗口全部被創(chuàng)建出來,我們勝利的返回到ProcessShellCommand處。顯示和更新主窗口,完成了WinApp::InitInstance :

                 // 主窗口已初始化,因此顯示它并對其進(jìn)行更新

                 pMainFrame->ShowWindow(m_nCmdShow);

                 pMainFrame->UpdateWindow();

             

             

             

            看一下至此的TRACE輸出,中間的DLL加載被去掉了:

            Before CMultiDocTemplate

            Before AddDocTemplate

            Before new CMainFrame

            CMainFrame::CMainFrame()

            Before pMainFrame->LoadFrame

            CMainFrame::PreCreateWindow entry         // 注意:PreCreateWindow 被兩次調(diào)用

            CMainFrame::PreCreateWindow entry

            CMainFrame::OnCreate entry before CMDIFrameWnd::OnCreate

            CMainFrame::OnCreate before m_wndToolBar.CreateEx

            CMainFrame::OnCreate before m_wndStatusBar.Create

            Before ParseCommandLine

            Before ProcessShellCommand

            CMDITestDoc::CMDITestDoc()       // 文檔對象被創(chuàng)建

            CChildFrame::CChildFrame()       // 子框架窗口被創(chuàng)建

            CChildFrame::PreCreateWindow entry

            CChildFrame::PreCreateWindow entry

            CChildFrame::PreCreateWindow entry

            CMDITestView::CMDITestView() entry   // 子框架窗口的 OnCreate 中創(chuàng)建了 View 窗口

            CMDITestView::PreCreateWindow entry

            CMDITestDoc::OnNewDocument() entry

            Before pMainFrame->ShowWindow

            Before pMainFrame->UpdateWindow

             

            // 退出時(shí)的 TRACE

            CMDITestView::~CMDITestView()

            CChildFrame::~CChildFrame()

            CMDITestDoc::~CMDITestDoc()

            CMainFrame::~CMainFrame()

            posted on 2009-03-29 10:25 弱水一瓢 閱讀(457) 評論(1)  編輯 收藏 引用

            評論

            # re: 溫故而知新,學(xué)習(xí)MFC框架如何創(chuàng)建的過程收藏 2009-03-29 21:37 Sunshine Alike

            字好大~ T_T  回復(fù)  更多評論   


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            <2009年3月>
            22232425262728
            1234567
            891011121314
            15161718192021
            22232425262728
            2930311234

            導(dǎo)航

            統(tǒng)計(jì)

            文章分類

            最新評論

            久久久无码精品亚洲日韩蜜臀浪潮 | 久久久SS麻豆欧美国产日韩| 久久伊人影视| 亚洲色欲久久久综合网东京热 | 欧美粉嫩小泬久久久久久久| 久久亚洲精品无码aⅴ大香| 成人久久综合网| 区久久AAA片69亚洲| 国产精品久久久久一区二区三区 | 思思久久好好热精品国产| 精品国产VA久久久久久久冰| 久久精品国产亚洲7777| a高清免费毛片久久| 国内精品久久久久影院薰衣草| 久久久久久免费一区二区三区| 国产亚洲精久久久久久无码77777 国产亚洲精品久久久久秋霞 | 久久国产成人午夜aⅴ影院| 日韩人妻无码精品久久免费一| 国内精品伊人久久久久网站| 久久水蜜桃亚洲av无码精品麻豆| 青青热久久国产久精品| 久久99国产精品99久久| 亚洲AV无一区二区三区久久 | 久久精品亚洲一区二区三区浴池| 午夜精品久久久久9999高清| 97超级碰碰碰碰久久久久 | 一本大道久久东京热无码AV| 久久99精品免费一区二区| 91精品国产色综久久| 欧美伊香蕉久久综合类网站| 久久久国产精品福利免费| 欧美熟妇另类久久久久久不卡| 久久精品国产2020| 久久精品国产色蜜蜜麻豆| 人人妻久久人人澡人人爽人人精品| 久久最新免费视频| 亚洲国产精品一区二区三区久久 | 久久精品中文字幕第23页| 一本久久久久久久| 久久国产一片免费观看| 精品视频久久久久|