深入分析MFC啟動流程

2021-06-19 10:04:09 字數 4746 閱讀 6218

預設情況下,c語言一般都有main函式,可是在mfc程式裡面我們一般會發現不了main函式,其實這個是有的。

注意:預設情況下。如在嵌入式領域,無論怎麼啟動,最終都會跳到乙個迴圈程式,當出現正常退出或者異常才會退出這個迴圈,執行緒處理函式一樣,所以main還是_tmain都是我們定義的入口函式,當然os或者庫也可以定義其他的,這個主函式其實只是乙個入口點。

看乙個簡單的c程式

int main(int argc, char *argv)

這裡會有傳入引數,執行迴圈體,返回語句

當然在window sdk程式設計中也會出現這個的,因為sdk程式設計一般都是自己建立視窗,以下在vs2012自動生成的**,在繪圖處理**中加入了hello的顯示

// hello.cpp : 定義應用程式的入口點。

//#include "stdafx.h"

#include "hello.h"

#define max_loadstring 100

// 全域性變數:

hinstance hinst; // 當前例項

tchar sztitle[max_loadstring]; // 標題欄文字

tchar szwindowclass[max_loadstring]; // 主視窗類名

// 此**模組中包含的函式的前向宣告:

atom myregisterclass(hinstance hinstance);

bool initinstance(hinstance, int);

lresult callback wndproc(hwnd, uint, wparam, lparam);

int_ptr callback about(hwnd, uint, wparam, lparam);

int apientry _twinmain(_in_ hinstance hinstance,

_in_opt_ hinstance hprevinstance,

_in_ lptstr lpcmdline,

_in_ int ncmdshow)

...// 主訊息迴圈:

while (getmessage(&msg, null, 0, 0)) //獲取訊息到msg,並從佇列中刪除它,沒有退出 }

return (int) msg.wparam;}//

// 函式: myregisterclass()

//// 目的: 註冊視窗類。

//atom myregisterclass(hinstance hinstance)

//// 函式: initinstance(hinstance, int)

//// 目的: 儲存例項控制代碼並建立主視窗

bool initinstance(hinstance hinstance, int ncmdshow)

showwindow(hwnd, ncmdshow);

updatewindow(hwnd);

return true;}//

// 函式: wndproc(hwnd, uint, wparam, lparam)

//// 目的: 處理主視窗的訊息。

//// wm_command - 處理應用程式選單

// wm_paint - 繪製主視窗

// wm_destroy - 傳送退出訊息並返回

////

lresult callback wndproc(hwnd hwnd, uint message, wparam wparam, lparam lparam)

case wm_destroy:

postquitmessage(0);

break;

default:

return defwindowproc(hwnd, message, wparam, lparam);

} return 0;

}

精簡以上main函式**

1. 註冊視窗類,包含一些公共的視窗類的一些屬性:atom myregisterclass(hinstance hinstance)

2. 建立視窗並顯示:bool initinstance(hinstance hinstance, int ncmdshow)

3. 獲取訊息並處理訊息:

while (getmessage(&msg, null, 0, 0))  //獲取訊息到msg,並從佇列中刪除它,沒有退出}

4. 訊息處理: 裡面使用了switch對不同的訊息進行處理:lresult callback wndproc(hwnd hwnd, uint message, wparam wparam, lparam lparam);

可以看出以上也是有傳入引數,訊息主體(主要是訊息迴圈處理),返回語句(正常退出或者異常退出)

;

// mfchellodlg.h : 標頭檔案

//#pragma once

// cmfchellodlg 對話方塊

class cmfchellodlg : public cdialogex

;

那麼mfc主函式在**呢?f10除錯後,會跳到主函式_twinmain

extern "c" int winapi

_twinmain(hinstance hinstance, hinstance hprevinstance,

_in_ lptstr lpcmdline, int ncmdshow)

#pragma warning(suppress: 4985)

而afxwinmain在vs安裝目錄就有,例如我的安裝目錄

c:\program files (x86)\vs 2012\vc\atlmfc\src\mfc\winmain.cpp

在這個檔案裡,如下

int afxapi afxwinmain(hinstance hinstance, hinstance hprevinstance,

_in_ lptstr lpcmdline, int ncmdshow)

nreturncode = pthread->exitinstance();

goto initfailure;

}//執行執行緒的迴圈函式

nreturncode = pthread->run();

...//執行緒終止

afxwinterm();

return nreturncode;

}

精簡以上**,就會發現其實是一樣的

1.初始化主框架,儲存引數 :   if (!afxwininit(hinstance, hprevinstance, lpcmdline, ncmdshow))

cmfchellodlg dlg;

m_pmainwnd = &dlg;

int_ptr nresponse = dlg.domodal();

4.迴圈處理函式:nreturncode = pthread->run(); run 獲取和計畫windows訊息,直到應用程式收到wm_quit

訊息。 如果執行緒的訊息佇列當前不包含訊息, run 呼叫 onidle 執行空閒時間處理。 傳入訊息轉到處理的特定的pretranslatemessage 成員函式然後標準鍵盤轉換的windows函式translatemessage。 最後dispatchmessage windows函式呼叫。

5. 銷毀應用程式: afxwinterm();這裡包括註冊的視窗類、執行緒模組和執行緒全域性結構體的銷毀

初始化函式的呼叫

在這裡我們似乎沒有發現create建立視窗的過程,怎麼回事,難道沒有??其實不是的,只是我們在第3步的時候遺漏了乙個地方:

cmfchellodlg dlg; //在棧上建立物件,便於退出時釋放(堆上也是可以的,但要退出時進行釋放)

dlg.domodal(); //視窗的顯示

那麼如何呼叫oninitdialog()進行初始化呢?

int_ptr cdialog::domodal()

-》 if (!createrundlgindirect(lpdialogtemplate, cwnd::fromhandle(hwndparent), hinst) && !g_bclosedbyenddialog)

-》bool cwnd::createdlgindirect(lpcdlgtemplate lpdialogtemplate, cwnd* pparentwnd, hinstance hinst)

-》 hwnd = ::createdialogindirect(hinst, lpdialogtemplate,pparentwnd->getsafehwnd(), afxdlgproc);

-》int_ptr callback afxdlgproc(hwnd hwnd, uint message, wparam, lparam)

afxdlgproc函式的**如下:

int_ptr callback afxdlgproc(hwnd hwnd, uint message, wparam, lparam)

return 0;

}

當得到的訊息是wm_initdialog且dlg不為空,就呼叫基類的pdlg->oninitdialog(),這個函式是虛函式而且子類進行了重寫,就會呼叫bool cmfchellodlg::oninitdialog()進行視窗的初始化。

MFC 程式啟動流程分析

一 mfc程式執行過程剖析 相信大家有點暈點了吧,實際程式設計中沒有必要深刻理解這麼多,這些大都是由mfc內部自動幫我們完成的。實際mfc程式設計過程中,其實懂得mfc程式中各個函式的執行流程即可。有時候過於追究mfc細節會白白浪費我們的精力,應該將主要精力放在使用mfc解決實際問題上。二 vc6中...

IsPostBack深入分析

1 ispostback 介紹 ispostback是 page類有乙個 bool型別的屬性,用來判斷針對當前 form的請求是第一次還是非第一次請求。當 ispostback true時表示非第一次請求,我們稱為 postback,當 ispostback false時表示第一次請求。在 asp....

深入分析ConcurrentHashMap

再多執行緒的情況下,如果使用hashmap,就會導致死迴圈,導致cpu利用率接近100 所以如果是併發的情況不要使用hashmap 導致死迴圈主要是這段 當在多執行緒的情況由於沒有同步導致,著段 在擴容的時候會執行 do while e null 執行緒安全的hashtable 容器 hashtab...