• <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)  編輯 收藏 引用

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            導航

            統計

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            文章分類

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久久久久国产精品无码超碰| 亚洲日韩欧美一区久久久久我| 亚洲AV无码久久精品成人 | 国产午夜精品久久久久免费视| 国产精品福利一区二区久久| 狠狠色综合久久久久尤物| 久久精品国产亚洲av麻豆图片 | 国产巨作麻豆欧美亚洲综合久久 | 精品久久久久久亚洲精品| 精品久久久久中文字幕一区| 久久久噜噜噜久久中文字幕色伊伊 | 国产Av激情久久无码天堂| 免费一级欧美大片久久网| 国内精品人妻无码久久久影院 | 国产精品9999久久久久| 欧美麻豆久久久久久中文| 久久99国产精品久久99| 亚洲色大成网站www久久九| 久久久久亚洲AV无码专区网站| 久久精品中文騷妇女内射| 思思久久精品在热线热| 久久午夜福利电影| 国产精品青草久久久久福利99| 欧美亚洲色综久久精品国产| 久久国产欧美日韩精品免费| 久久国产热这里只有精品| 国产精品禁18久久久夂久 | 国产一区二区三精品久久久无广告| 久久精品无码午夜福利理论片| 国产香蕉久久精品综合网| 亚洲国产天堂久久久久久| 久久免费观看视频| 国产女人aaa级久久久级| 久久精品国产91久久麻豆自制 | 日本精品久久久中文字幕| 91精品国产高清久久久久久io| 无码人妻精品一区二区三区久久久| 伊人久久亚洲综合影院| 国内精品久久久久影院薰衣草 | 少妇精品久久久一区二区三区| 亚洲va国产va天堂va久久|