• <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>

            winlinglin

            MFC學習筆記(一)

            Win32應用程序有條明確的主線:
             (1) 進入WinMain函數
             (2) 設計一個Window
             (3) 注冊這個Window
             (4) 建立這個Window
             (5) 顯示和更新這個Window
             (6) 進入消息循環
             
            好,我就先找WinMain函數吧。
            我在C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src\mfc的appmodul.cpp的23行中找到了以下代碼:
            extern "C" int WINAPI
            _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
             _In_ LPTSTR lpCmdLine, int nCmdShow)
            #pragma warning(suppress: 4985)
            {
             // call shared/exported WinMain
             return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
            }

            _tWinMain是一個宏,詳細為: #define _tWinMain WinMain
            所以這個確實是我們要找的WinMain函數

            從代碼中看出,WinMain將參數全部交給AfxWinMain,來處理。
            好,我又找AfxWinMain這個函數。

            我在winmain.cpp的19行找到了AfxWinMain函數。
            代碼:
            int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
             _In_ LPTSTR lpCmdLine, int nCmdShow)
            {
             ASSERT(hPrevInstance == NULL);   // ASSERT在程序運行時它計算括號內的表達式,如果表達式為FALSE (0),
                       // 程序將報告錯誤,并終止執行。如果表達式不為0,則繼續執行后面的語句。
                       // ASSERT只有在Debug版本中才有效,如果編譯為Release版本則被忽略。
                       // assert()的功能類似,它是ANSI C標準中規定的函數,它與ASSERT的一個重要區別是可以用在Release版本中。
             int nReturnCode = -1;
             // AfxGetThread和 AfxGetApp 都是全局函數
             CWinThread* pThread = AfxGetThread();  // 獲得正在執行的線程,Must be called from within the desired thread.
             CWinApp* pApp = AfxGetApp();    // 獲得A pointer to the single CWinApp object for the application

             // AFX internal initialization
                        // This function is called by the MFC-supplied WinMain function, as part of the CWinApp initialization of a GUI-based
                        // application, to initialize MFC.
             if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))  
              goto InitFailure;

             // App global initializations (rare)
             if (pApp != NULL && !pApp->InitApplication())  //InitApplication已經過時,用InitInstance代替,完成MFC內部管理方面的工作
              goto InitFailure;

             // Perform specific initializations
             if (!pThread->InitInstance())  // 初始化Instance,在每個 a copy of the program runs的時候,虛函數
             {
              if (pThread->m_pMainWnd != NULL)
              {
               TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
               pThread->m_pMainWnd->DestroyWindow();   // m_pMainWnd holds a pointer to the application's main window.返回一個CWnd.
                           // cWnd Destroys the attached Windows window.
              }
              nReturnCode = pThread->ExitInstance();    // to exit this instance of the thread
              goto InitFailure;
             }
             nReturnCode = pThread->Run();  

            InitFailure:
            #ifdef _DEBUG
             // Check for missing AfxLockTempMap calls
             if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
             {
              TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n",
               AfxGetModuleThreadState()->m_nTempMapLock);
             }
             AfxLockTempMaps();
             AfxUnlockTempMaps(-1);
            #endif

             AfxWinTerm();
             return nReturnCode;
            }


            找到了WinMain函數后,看了下MFC為我生成的類:
            1. CTestApp  2. CTestView 3. CMainFrame  4. CTestDoc  5. CAboutDlg
            查看CTestApp.cpp,發現了一個全局的CTestApp theApp,因為全局對象必須在main函數之前產生并初始化,所以應用程序調用的順序應該是
            CTestApp的構造函數 -> WinMain函數
            又發現class CTestApp : public CWinApp,子類的構造函數在父類的構造函數調用之后調用,所以就搜索CWinApp吧。

            在appcore.cpp的368行發現以下代碼:
            CWinApp::CWinApp(LPCTSTR lpszAppName)  // 此處的lpszAppName有個默認參數NULL
            {
             if (lpszAppName != NULL)
              m_pszAppName = _tcsdup(lpszAppName); // 為lpszAppName分配內存
             else
              m_pszAppName = NULL;

             // initialize CWinThread state
             AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
             ENSURE(pModuleState);
             AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
             ENSURE(pThreadState);
             ASSERT(AfxGetThread() == NULL);
             pThreadState->m_pCurrentWinThread = this;  // 如果有子類繼承了CWinApp, this就是子類
             ASSERT(AfxGetThread() == this);
             m_hThread = ::GetCurrentThread();
             m_nThreadID = ::GetCurrentThreadId();

             // initialize CWinApp state
             ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please
             pModuleState->m_pCurrentWinApp = this;   // 如果有子類繼承了CWinApp, this就是子類
             ASSERT(AfxGetApp() == this);

             // in non-running state until WinMain
             m_hInstance = NULL;
             m_hLangResourceDLL = NULL;v
             m_pszHelpFilePath = NULL;
             m_pszProfileName = NULL;
             m_pszRegistryKey = NULL;
             m_pszExeName = NULL;
             m_pRecentFileList = NULL;
             m_pDocManager = NULL;
             m_atomApp = m_atomSystemTopic = NULL;
             m_lpCmdLine = NULL;
             m_pCmdInfo = NULL;

             // initialize wait cursor state
             m_nWaitCursorCount = 0;
             m_hcurWaitCursorRestore = NULL;

             // initialize current printer state
             m_hDevMode = NULL;
             m_hDevNames = NULL;
             m_nNumPreviewPages = 0;     // not specified (defaults to 1)

             // initialize DAO state
             m_lpfnDaoTerm = NULL;   // will be set if AfxDaoInit called

             // other initialization
             m_bHelpMode = FALSE;
             m_eHelpType = afxWinHelp;
             m_nSafetyPoolSize = 512;        // default size
            }

            然后是CTestApp的構造函數的調用。
            在CTestApp的聲明中,它重寫了InitInstance函數,如下:
            BOOL CTestApp::InitInstance()
            {
             AfxEnableControlContainer();  //Call this function in your application object's InitInstance function
                      //to enable support for containment of ActiveX controls

             // Standard initialization
             // If you are not using these features and wish to reduce the size
             //  of your final executable, you should remove from the following
             //  the specific initialization routines you do not need.

            // In MFC 5.0, Enable3dControls and Enable3dControlsStatic are obsolete because their functionality is incorporated
            // into Microsoft's 32-bit and 64-bit operating systems.  
             
            #ifdef _AFXDLL
             Enable3dControls();   // Call this when using MFC in a shared DLL
            #else
             Enable3dControlsStatic(); // Call this when linking to MFC statically
            #endif

             // Change the registry key under which our settings are stored.
             // TODO: You should modify this string to be something appropriate
             // such as the name of your company or organization.
             SetRegistryKey(_T("Local AppWizard-Generated Applications"));

             LoadStdProfileSettings();  // Load standard INI file options (including MRU)

             // Register the application's document templates.  Document templates
             //  serve as the connection between documents, frame windows and views.

             CSingleDocTemplate* pDocTemplate;  // 單文檔程序的模板生成
             pDocTemplate = new CSingleDocTemplate(
              IDR_MAINFRAME,
              RUNTIME_CLASS(CTestDoc),
              RUNTIME_CLASS(CMainFrame),       // main SDI frame window
              RUNTIME_CLASS(CTestView));
             AddDocTemplate(pDocTemplate);

             // Parse command line for standard shell commands, DDE, file open
             CCommandLineInfo cmdInfo;   // 對命令查詢分析
             ParseCommandLine(cmdInfo);

             // Dispatch commands specified on the command line
             if (!ProcessShellCommand(cmdInfo))
              return FALSE;

             // The one and only window has been initialized, so show and update it.
             m_pMainWnd->ShowWindow(SW_SHOW);  //顯示和更新窗口
             m_pMainWnd->UpdateWindow();

             return TRUE;
            }


            有了WinMain函數,也找到了顯示和更新窗口的語句,但是從哪里開始設計窗口,注冊窗口,建立窗口呢?
            我又搜索了WNDCLASS,在wincore.cpp的4495行發現了與設計窗口時很像的函數BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
            發現MS已經在里面為我注冊了一些窗口,我只要選擇自己想要的樣式就可以了。

            那么如何建立一個窗口呢?我又搜索了CreateWindow,在wincore.cpp的675行中有個BOOL CWnd::CreateEx函數。
            里面有調用CreateWindowEx。這個函數還調用了一個叫PreCreateWindow的函數,這個函數主要是確定在建立窗口之前,確保要建立的窗口已經注冊了。

            好了,一切都準備好了。最后就是進入消息循環。

            posted on 2009-03-03 01:24 wil 閱讀(1833) 評論(0)  編輯 收藏 引用

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

            導航

            統計

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            文章分類

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久久久久a亚洲欧洲aⅴ | 久久婷婷五月综合国产尤物app| 久久综合给合综合久久| 伊人久久一区二区三区无码| 无遮挡粉嫩小泬久久久久久久| 久久99久久99精品免视看动漫| 亚洲国产精品婷婷久久| 欧美一区二区久久精品| 久久久久久国产精品免费无码 | 久久人人超碰精品CAOPOREN| 亚洲精品NV久久久久久久久久 | 亚洲午夜无码AV毛片久久| 国内精品久久久久久99| 久久久久综合国产欧美一区二区| 久久精品国产色蜜蜜麻豆| 精品一区二区久久| 午夜不卡久久精品无码免费| 国产精品午夜久久| 久久免费精品视频| 久久久久久久精品妇女99| 亚洲国产二区三区久久| 久久亚洲国产成人精品性色| 久久夜色精品国产亚洲av| 国产精品久久一区二区三区 | 欧美午夜精品久久久久免费视| 国产成人香蕉久久久久| av午夜福利一片免费看久久| 狠狠色婷婷久久综合频道日韩| 久久青青色综合| 久久精品这里只有精99品| 久久久久久久久久久免费精品| 国产精品岛国久久久久| 国产亚洲综合久久系列| 久久精品无码专区免费东京热| 久久热这里只有精品在线观看| 久久免费国产精品| 天天影视色香欲综合久久| 一级A毛片免费观看久久精品| 久久99精品久久久久久噜噜| 尹人香蕉久久99天天拍| 欧美午夜A∨大片久久|