MFC程序產生、啓動全講解

1、Applicate Object產生,內存於是獲得配置,初值也設立,也即調用了CWinApp的構造函數
2、CWinApp --> AfxWinMain,它先執行 AfxWinInit --> AfxInitThread 。把消息隊列儘量加大到 96
3、AfxWinMain 執行 InitApplication ,這個函數爲CWinApp的虛函數,通常不需要改寫,主要爲MFC內部管理作一些設置
ps.以前的InitApplication是註冊窗口類的場所!!
4、AfxWinMain 執行 InitInstance,這也是CWinApp的一個虛函數,通常是要改寫的
5、InitInstance new 一個 CSingleDocTemplate 或者CMultiDocTemplate 對象,規劃 Document、View、DocumentFrame三者之間的關係
6、InitInstance  調用AddDocTemplate,主要爲了處理 IDR_MAINFRAME
ps.如果是MDI的情況,這之後首先需要調用:

 程序代碼
    CMainFrame* pMainFrame = new CMainFrame;
    if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
        return FALSE;
    m_pMainWnd = pMainFrame;
這樣創建主窗口,後面的步驟中創建的是子窗口的過程。
7、InitInstance  調用 ParseCommandLine
ParseCommandLine作用:分析命令行參數,如果沒有命令行參數 ,ParseCommandLine 就假定用戶想新建一個文檔,於是設置一個FileNew命令
8、InitInstance  調用 ProcessShellCommand 處理 FileNew命令,將調用 CWinApp::OnFileNew
9、CWinApp::OnFileNew --> CDocManager::OnFileNew --> CWinApp::OpenDocumentFile(NULL) --> CDocManager::OpenDocumentFile(NULL) --> CSingleDocTemplate::OpenDocumentFile(NULL) 或者 CMultiDocTemplate::OpenDocumentFile(NULL)
ps.這裏傳入的參數是NULL,如果是打開一個已經存在的文件時,傳入的就是文件的路徑名
10、CSingleDocTemplate::OpenDocumentFile
10-1、【Document】CreateNewDocument(); 動態創建Document對象 (類型信息根據本身程序原先的窗口)

 程序代碼
CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();
此時創建的是自定義的一個CDocument子類,例如 “CTestDoc”
10-2、【Frame】CreateNewFrame();  這個函數先動態創建Frame對象,然後調用LoadFrame
ps. 前者只是建立一個類型空的數據結構,後者LoadFrame纔是創建窗口的地方。

 程序代碼
CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
pFrame->LoadFrame(m_nIDResource,
WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, // default frame styles
NULL, &context)
此時創建的一個自定義的一個CFrameWnd子類,一般自動名爲“CMainFrame”

另外Frame主窗口創建具體過程:

 引用內容
LoadFrame --> Create
    (1) CFrameWnd::Create
                   A、::LoadMenu 創建菜單對象結構,並且返回菜單對象句柄
             B、CWnd::CreateEx
    (2) CWnd::CreateEx
                   A、CFrameWnd::PreCreateWindow  註冊窗口類的地方,以前在InitApplication
                   B、AfxHookWindowCreate
                         hook窗口處理函數交由全局函數AfxWndProc處理
                 具體操作見《深入淺出MFC》P418 米諾斯托與西休斯
             C、調用Win32 API ::CreateWindowEx創建窗口 (這裏需要傳入前面的菜單句柄)

11、此時 CreateWindowEx 產生消息 WM_Create,於是調用 CMainFrame::OnCreate,這個函數將創建工具欄和狀態欄!!
12、【View】View什麼時候生成?當窗口產生時會有一個WM_Create消息。此時:
WM_Create --> CFrameWnd::OnCreate --> CFrameWnd::OnCreateHelper --> CFrameWnd::OnCreateClient --> CFrameWnd::CreateView

 程序代碼
CWnd* pView = (CWnd*)pContext->m_pNewViewClass->CreateObject();
pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
CRect(0,0,0,0), this, nID, pContext))

13、創建完“三口組”,又回到 CSingleDocTemplate::OpenDocumentFile 。
此時調用 OnNewDocument,子類若重載了,就調用子類的 CTestDoc::OnNewDocument
14、如果子類沒有重載,那麼就調用基類的OnNewDocument ,基類的OnNewDocument 會調用DeleteContents,這個函數的作用:
當從磁盤文件中載入文件,首先需要將現有文檔對象的內容清除掉,這就交由DeleteContents處理

15、CSingleDocTemplate::OpenDocumentFile 接着調用 CDocTemplate::InitialUpdateFrame --> CFrameWnd::InitialUpdateFrame
16、CFrameWnd::InitialUpdateFrame 中 bMakeVisible=true,所以
SendMessageToDescendants(WM_INITIALUpdate, 0, 0, TRUE, TRUE);
17、消息 WM_INITIALUpdate 導致 自定義的CView子類的 重載的 OnInitialUpdate 的調用。假設爲:
CTestView::OnInitialUpdate
ps.沒有重載當然調用CView的 OnInitialUpdate。

 引用內容
ps.構造函數所做的工作越少,程序失敗的機會就越小,所以在一些初始的函數中加入變量初始化工作纔是最佳選擇:例如在 CDocument::OnNewDocument、CView::OnInitialUpdate 等地方!!
在例如,進行窗口特性的控制最好放在 PreCreateWindow 函數中~~
18、此時導致 CTestView::OnUpdate 的調用
19、回到 CFrameWnd::InitialUpdateFrame 。它將調用 CFrameWnd::ActivateFrame虛成員函數,如果衝在了(一般都是),將調用 CMainFrame::ActivateFrame.
作用是 激活具有菜單、視圖窗口和工具欄的主框架窗口。
但是此時窗口還沒有顯示,在這裏可以定義窗口激活的方式,例如設置全屏激活等等...

 程序代碼
nCmdShow = SW_MAXIMIZE;
CFrameWnd::ActivateFrame(nCmdShow);
20、回到調用ShowWindow顯示主窗口
21、UpdateWindow 發出 WM_PAINT 消息

調用 CFrameWnd::ActivateFrame虛成員函數,顯示具有菜單、視圖窗口和工具欄的主框架窗口。

發佈了30 篇原創文章 · 獲贊 2 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章