一個Windows應用程式至少由兩部分組成:消息處理和視窗過程。在MFC中,由CWinApp和CWnd來分别處理這些操作。
CWinApp負責初始化,建立一個或多個視窗。CWinApp由CWinThread派生。CWinThread的成員函數Run,維護GetMessage() ... DispatchMessage()等消息循環。
每個MFC子產品都必須寫一個類CYourApp,這個類從CWinApp派生,它具體實作了此子產品要做的事情。
每個子產品都擁有一個CYourApp的執行個體,但是CYourApp的執行個體theApp不是_tWinMain中被建立的。在進入主程式之前,執行個體就已經建立出來。MFC中有非常多的全局變量,theApp就是一個全局變量。為什麼theApp會成為全局變量呢?我想是微軟希望掩蓋_tWinMain函數的細節,那麼_tWinMain自然不會知道每個項目的CWinApp的派生類的名稱,也就無從生成此對象的執行個體了。
其實,在MFC中,最大、最重要的一個全局變量是一個無文檔說明的_afxBaseModuleState,其類型是結構體_AFX_BASE_MODULE_STATE。_AFX_BASE_MODULE_STATE的所有秘密在于其基類AFX_MODULE_STATE。AFX_MODULE_STATE包括很多關于子產品的核心資訊,比如子產品執行個體句柄,資源子產品執行個體,CYourApp的指針、應用程式的名字、指向應用程式的運作時類資訊結構連結清單中的第一個節點的指針。當theApp被生成後,就會被記錄到AFX_MODULE_STATE中。當然,做為MFC的使用者,是不需要了解AFX_MODULE_STATE的具體細節的。MFC很體貼的提供了很多AfxXXX的全局函數,通過這些全局函數,我們就能獲得AFX_MODULE_STATE中的小秘密了。比如AfxGetApp()可以獲得theApp執行個體,AfxGetInstanceHandle獲得子產品執行個體句柄等。
CYourApp(即CWinApp)被建立後,将在_tWinMain中被初始化。_tWinMain首先會調用CWinApp的InitApplication,在此函數中初始化CWinApp的某些成員變量,比如CDocManager對象等。然後調用InitInstance,通常CYourApp會重載這些函數,在此函數中我們會初始化COM環境等東西,然後建立文檔視圖模型,建立并顯示主視窗。最後會調用CWinApp的Run,開始我們的消息之旅。當使用者選擇退出應用程式後,程式控制權從Run中傳回到_tWinMain中,函數會做一些對象清理之類的工作,最後成功退出。
http://blog.sina.com.cn/s/blog_660ca10d0100lg0z.html
---------------------------------------------------------------------------------------------------------------------------------------
基本資訊
CWinApp為應用程式類
MFC 中的主應用程式類封裝用于 Windows 作業系統的應用程式的初始化、運作和終止。基于 架構 生成的應用程式必須有且僅有一個從 CWinApp 派生的類的對象。在建立視窗之前先構造該對象。
CWinApp 是從 CWinThread 派生的,後者表示可能具有一個或多個線程的應用程式的主執行線程。在最新版本的 MFC 中,InitInstance、Run、ExitInstance 和 OnIdle 成員函數實際位于 CWinThread 類中。此處将這些函數作為 CWinApp 成員來探讨,因為探讨所關心的是對象作為應用程式對象而不是 主線程 的角色。
注意
應用程式類構成應用程式的主執行線程。使用 Win32 API 函數還可以建立輔助執行線程。這些線程可以使用 MFC 庫。有關更多資訊,請參見多線程程式設計。
與用于 Windows 作業系統的任何程式一樣,架構應用程式也具有 WinMain 函數。但在架構應用程式中不必編寫 WinMain。它由類庫提供,并在應用程式啟動時調用。WinMain 執行注冊 視窗類 等标準服務。然後它調用應用程式對象的成員函數來初始化和運作應用程式。(可通過重寫由 WinMain 調用的 CWinApp 成員函數來自定義 WinMain。)
為初始化應用程式,WinMain 調用應用程式對象的 InitApplication 和 InitInstance 成員函數。為運作應用程式的 消息循環 ,WinMain 調用 Run 成員函數。在終止時,WinMain 調用應用程式對象的 ExitInstance 成員函數。下圖顯示了架構應用程式中的執行順序。
CWinApp - 執行順序
注意 本文中以粗體顯示的名稱訓示由 Microsoft 基礎類庫和 Visual C++ 提供的元素。以 monospaced 類型顯示的名稱訓示您建立或重寫的元素。
基于MFC的應用程式有一個 應用對象 ,它是CWinApp派生類的對象,該對象代表了應用程序的 主線程 。當線程執行完并退出線程時,由于程序中沒有其他線程存在,程序自動結束。類CWinApp從CWinThread派生出來,CWinThread是 使用者接口 線程的基本類。我們在編寫使用者接口線程時,需要從CWinThread派生我們自己的線程類,ClassWizard可以幫助我們完成這個工作。
先用ClassWizard派生一個新的類,設定 基類 為CwinThread。注意:類的 DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE 宏是必需的,因為建立線程時需要動态建立類的對象。根據需要可将初始化和結束代碼分别放在類的InitInstance和ExitInstance函數中。如果需要建立視窗,則可在InitInstance函數中完成。然後建立線程并啟動線程。可以用兩種方法來建立使用者接口線程,MFC提供了兩個版本的 AfxBeginThread 函數,其中一個用于建立使用者接口線程。第二種方法分為兩步進行:首先,調用線程類的 構造函數 建立一個線程對象;其次,調用CWinThread::CreateThread函數來建立該線程。線程建立并啟動後,線上程函數執行過程中一直有效。如果是線程對象,則在對象删除之前,先結束線程。CWinThread已經為我們完成了線程結束的工作。
CWinApp - CWinApp類成員
資料成員
m_pszAppName | 指定了應用程式的名字 |
m_hInstance | 辨別了應用程式的目前執行個體 |
m_hPrevInstance | 在32位應用程式中被設為NULL |
m_lpCmdLine | 指向一個以null結尾的字元串,指定了應用程式的指令行 |
m_nCmdShow | 指定最初如何顯示視窗 |
m_bHelpMode | 指明使用者是否處于Help上下文模式(通常用SHIFT+F1激活) |
m_pActiveWnd | 當一個OLE伺服器是現場可激活時,它指向容器應用程式的主視窗 |
m_pszExeName | 應用程式的子產品名字 |
m_pszHelpFilePath | 應用程式的幫助檔案的路徑 |
m_pszProfileName | 應用程式的。INI檔案名 |
m_pszRegistryKey | 用于确定儲存應用程式主要設定的完整的系統資料庫鍵 |
m_pDocManager | 用于儲存文檔模闆管理類的指針(MSDN中沒有這個資料成員) |
構造函數
CWinApp 構造一個CWinApp對象
操作符
LoadCursor | 載入光标資源 |
LoadStandardCursor | 載入WINDOWS.H中IDC_常量所指定的Windows預定義光标 |
LoadOEMCursor | 載入WINDOWS.H中OCR_常量所指定的WindowsOEM預定義光标 |
LoadIcon | 載入圖示資源 |
LoadStandardIcon | 載入WINDOWS.H中IDI_常量所指定的Windows預定義圖示 |
LoadOEMIcon | 載入WINDOWS.H中OIC_常量所指定的WindowsOEM預定義圖示 |
RunAutomated | 檢查應用程式的指令行是否指定/Automation選項。已不用。應當在調用ParseCommandLine之後使用CCommandLineInfo::m_bRunEmbedded中的值 |
RunEmbedded | 檢查應用程式的指令行是否指定/Embedding選項。已不用。應當在調用ParseCommandLine之後使用CCommandLineInfo::m_bRunEmbedded中的值 |
ParseCommandLine | 解析指令行中的每個參數和标志 |
ProcessShellCommand | 處理指令行參數和标志 |
GetProfileInt | 從應用程式的。INI檔案的一個入口中擷取一個整數 |
WriteProfileInt | 将一個整數寫到應用程式的。INI檔案的入口 |
GetProfileString | 從應用程式的。INI檔案的一個入口中擷取一個字元串 |
WriteProfileString | 将一個字元串寫到應用程式的。INI檔案的入口 |
AddDocTemplate | 将一個文檔模闆加到應用程式的可用文檔模闆清單中 |
GetFirstDocTemplatePosition | 擷取第一個文檔模闆的位置 |
GetNextDocTemplate | 獲得文檔模闆的位置。可以遞歸調用 |
OpenDocumentFile | 由架構調用,用以從檔案打開一個文檔 |
AddToRecentFileList | 将一個檔案名加入最近使用(MRU)的檔案清單 |
SelectPrinter | 選擇先前由使用者在列印對話框中指定的列印機 |
CreatePrinterDC | 建立一個列印機裝置環境 |
GetPrinterDeviceDefaults | 獲得預設的列印機裝置 |
可重載的函數
InitInstance | 可被重載以執行Windows的執行個體初始化,比如建立視窗對象 |
Run | 運作預設的消息循環。可被重載以定制消息循環 |
OnIdle | 可被重載以執行應用程式指定的空閑時處理 |
ExitInstance | 可被重載以在應用程式結束時執行清除操作 |
HideApplication | 在關閉所有的文檔之前隐藏應用程式 |
CloseAllDocuments | 關閉所有打開的文檔 |
PreTranslateMessage | 在消息被分派到Windows函數::TranslateMessage和::DispatchMessage之前過濾消息 |
SaveAllModified | 提示使用者儲存所有改變了的文檔 |
DoMessageBox | 為應用程式實作AfxMessageBox |
ProcessMessageFilter | 在消息到達應用程式之前截取特定的消息 |
ProcessWndProcException | 截取應用程式的消息和指令處理函數抛出的未被處理的異常 |
DoWaitCursor | 打開或關閉等待光标 |
OnDDECommand | 架構調用這個函數以響應動态資料交換(DDE)執行指令 |
WinHelp | 調用Windows的WinHelp函數 |
初始化
LoadStdProfileSettings | 載入标準的。INI檔案設定并允許MRU檔案清單特性 |
SetDialogBkColor | 設定對話框和消息框的預設背景顔色 |
SetRegistryKey | 使應用程式的設定儲存在系統資料庫中,而不是。INI檔案中 |
EnableShellOpen | 允許使用者通過Windows的檔案管理器打開資料檔案 |
RegisterShellFileTypes | 在Windows的檔案管理器中注冊所有的應用程式文檔類型 |
Enable3dControls | 使控件具有三維外觀(動态庫) |
Enable3dControlsStatic | 使控件具有三維外觀(靜态庫) |
指令操作
OnFileNew | 實作ID_FILE_NEW指令 |
OnFileOpen | 實作ID_FILE_NEW指令 |
OnFilePrintSetup | 實作ID_FILE_PRINT_SETUP指令 |
OnContextHelp | 處理應用程式内的SHIFT+F1指令 |
OnHelp | 處理應用程式内的F1幫助指令(使用目前的上下文) |
OnHelpIndex | 處理ID_HELP_INDEX指令,提供預設的幫助主題 |
OnHelpFinder | 處理ID_HELP_FINDER和ID_DEFAULT_HELP指令 |
OnHelpUsing | 處理ID_HELP_USING指令 |
http://www.baike.com/wiki/CWinApp