• <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>
            隨筆 - 42  文章 - 3  trackbacks - 0
            <2012年3月>
            26272829123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(2)

            隨筆檔案

            文章檔案

            網頁收藏

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            例子是一個mfc的對話框,用vc調試器查看了一個程序從生成初始化到接受消息的流程。從產生到結束的基本流程是這樣的:
            KERNEL32->WinMainCRTStartup()->_tWinMain(開始)->AfxWinMain(開始)->AfxGetThread()->AfxWinInit()->InitApplication()->InitInstance()->DoModal()->RunModalLoop()->ExitInstance()->AfxWinMain(結束)->_tWinMain(結束)

            1、KERNEL32
            kernel32.dll是Windows9x/Me中非常重要的32位動態鏈接庫文件,屬于內核級文件。它控制著系統的內存管理、數據的輸入輸出操作和中斷處理,當Windows啟動時,kernel32.dll就駐留在內存中特定的寫保護區域,使別的程序無法占用這個內存區域。

            2、WinMainCRTStartup()函數
              程序默認的基地址(EXE文件默認為0x400000,DLL默認為x10000000),操作系統裝載一個程序時總是試著先從這個基地址開始。一般Win32的程序,EXE的入口為WinMain,DLL的入口為DllEntryPoint。默認情況下,通過一個C的運行時庫函數來實現:控制臺程序采用mainCRTStartup (或wmainCRTStartup)去調用程序的main (或wmain)函數;Windows程序采用WinMainCRTStartup (或 wWinMainCRTStartup)調用程序的WinMain (或 wWinMain,必須采用__stdcall調用約定);DLL采用_DllMainCRTStartup調用DllMain函數(必須采用__stdcall調用約定)。
            它負責:
              * 檢索指向新進程的完整命令行指針;
              * 檢索指向新進程的環境變量的指針;
              * 對c/c++運行時的全局變量進行初始化;
              * 對c運行期的內存單元分配函數(比如malloc,calloc)和其他低層I/O例程使用的內存棧     進行初始化。
              * 為C++的全局和靜態類調用構造函數。
              當這些初始化工作完成后,該啟動函數就調用wWinMain函數進入應用程序的執行。
            當wWinMain函數執行完畢返回時,wWinMainCRTStartup啟動函數就調用c運行期的exit()函
            數,將返回值(nMainRetVal)傳遞給它。
              之后exit()便開始收尾工作:
              * 調用由_onexit()函數調用和注冊的任何函數。
              * 為C++的全局和靜態類調用析構函數;
              * 調用操作系統的ExitProcess函數,將nMainRetVal傳遞給它,這使得操作系統能夠撤銷     進程并設置它的exit  代碼。
            最小體積的win32程序:(不要編譯缺省庫)
            #pragma comment (linker, "/SUBSYSTEM:WINDOWS")
            #pragma comment (linker, "/NODEFAULTLIB")
            int WinMainCRTStartup()
            {
             return 0;
            }

            3、WinMain()函數
            _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
             LPTSTR lpCmdLine, int nCmdShow)
            {
             // call shared/exported WinMain
             return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
            }

            4、AfxWinMain()函數
            int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
             LPTSTR lpCmdLine, int nCmdShow)
            {
             ASSERT(hPrevInstance == NULL);

             int nReturnCode = -1;
             CWinThread* pThread = AfxGetThread();
             CWinApp* pApp = AfxGetApp();

             // AFX internal initialization
             if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
              goto InitFailure;

             // App global initializations (rare)
             if (pApp != NULL && !pApp->InitApplication())
              goto InitFailure;

             // Perform specific initializations
             if (!pThread->InitInstance())
             {
              if (pThread->m_pMainWnd != NULL)
              {
               TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
               pThread->m_pMainWnd->DestroyWindow();
              }
              nReturnCode = pThread->ExitInstance();
              goto InitFailure;
             }
             nReturnCode = pThread->Run();

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

             AfxWinTerm();
             return nReturnCode;
            }

            5、AfxGetThread()函數
            CWinThread* AFXAPI AfxGetThread()
            {
             // check for current thread in module thread state
             AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
             CWinThread* pThread = pState->m_pCurrentWinThread;

             // if no CWinThread for the module, then use the global app
             if (pThread == NULL)
              pThread = AfxGetApp();

             return pThread;
            }

            6、AfxWinInit()函數
            BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,
             LPTSTR lpCmdLine, int nCmdShow)
            {
             ASSERT(hPrevInstance == NULL);

             // handle critical errors and avoid Windows message boxes
             SetErrorMode(SetErrorMode(0) |
              SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);

             // set resource handles
             AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
             pModuleState->m_hCurrentInstanceHandle = hInstance;
             pModuleState->m_hCurrentResourceHandle = hInstance;

             // fill in the initial state for the application
             CWinApp* pApp = AfxGetApp();
             if (pApp != NULL)
             {
              // Windows specific initialization (not done if no CWinApp)
              pApp->m_hInstance = hInstance;
              pApp->m_hPrevInstance = hPrevInstance;
              pApp->m_lpCmdLine = lpCmdLine;
              pApp->m_nCmdShow = nCmdShow;
              pApp->SetCurrentHandles();
             }

             // initialize thread specific data (for main thread)
             if (!afxContextIsDLL)
              AfxInitThread();

             return TRUE;
            }

            7、InitApplication() 函數
            BOOL CMy1App::InitApplication()
            {
             // TODO: Add your specialized code here and/or call the base class
             AfxMessageBox("InitApplication");
             return CWinApp::InitApplication();
            }
            BOOL CWinApp::InitApplication()
            {
             if (CDocManager::pStaticDocManager != NULL)
             {
              if (m_pDocManager == NULL)
               m_pDocManager = CDocManager::pStaticDocManager;
              CDocManager::pStaticDocManager = NULL;
             }

             if (m_pDocManager != NULL)
              m_pDocManager->AddDocTemplate(NULL);
             else
              CDocManager::bStaticInit = FALSE;

             return TRUE;
            }

            8、InitInstance()函數
            AfxWinMain函數里面的if (!pThread->InitInstance())會調用程序CMy1App的InitInstance函數:
            BOOL CMy1App::InitInstance()
            {
             AfxEnableControlContainer();
            AfxMessageBox("InitInstance");
             // 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.

            #ifdef _AFXDLL
             Enable3dControls();   // Call this when using MFC in a shared DLL
            #else
             Enable3dControlsStatic(); // Call this when linking to MFC statically
            #endif

             CMy1Dlg dlg;//調用CMy1Dlg的構造函數
             m_pMainWnd = &dlg;
             int nResponse = dlg.DoModal();
             if (nResponse == IDOK)
             {
              // TODO: Place code here to handle when the dialog is
              //  dismissed with OK
             }
             else if (nResponse == IDCANCEL)
             {
              // TODO: Place code here to handle when the dialog is
              //  dismissed with Cancel
             }

             // Since the dialog has been closed, return FALSE so that we exit the
             //  application, rather than start the application's message pump.
             return FALSE;
            }

            9、AfxWinMain()函數里面的主要的循環體,在這里:
                    if (!pThread->InitInstance())//主要是模式對話框調用,對話框關閉以后InitInstance函數才會結束
             {
              if (pThread->m_pMainWnd != NULL)
              {
               TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
               pThread->m_pMainWnd->DestroyWindow();
              }
              nReturnCode = pThread->ExitInstance();
              goto InitFailure;
             }
             nReturnCode = pThread->Run();//非模式對話框和一般程序調用這個循環

            InitInstance函數調用了dlg.DoModal()函數,以下是DoModal()函數:
            int CDialog::DoModal()
            {
             // can be constructed with a resource template or InitModalIndirect
             ASSERT(m_lpszTemplateName != NULL || m_hDialogTemplate != NULL ||
              m_lpDialogTemplate != NULL);

             // load resource as necessary
             LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate;
             HGLOBAL hDialogTemplate = m_hDialogTemplate;
             HINSTANCE hInst = AfxGetResourceHandle();
             if (m_lpszTemplateName != NULL)
             {
              hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);
              HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
              hDialogTemplate = LoadResource(hInst, hResource);
             }
             if (hDialogTemplate != NULL)
              lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);

             // return -1 in case of failure to load the dialog template resource
             if (lpDialogTemplate == NULL)
              return -1;

             // disable parent (before creating dialog)
             HWND hWndParent = PreModal();
             AfxUnhookWindowCreate();
             BOOL bEnableParent = FALSE;
             if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
             {
              ::EnableWindow(hWndParent, FALSE);
              bEnableParent = TRUE;
             }

             TRY
             {
              // create modeless dialog
              AfxHookWindowCreate(this);
              if (CreateDlgIndirect(lpDialogTemplate,
                  CWnd::FromHandle(hWndParent), hInst))//創建對話框的窗口
              {
               if (m_nFlags & WF_CONTINUEMODAL)
               {
                // enter modal loop
                DWORD dwFlags = MLF_SHOWONIDLE;
                if (GetStyle() & DS_NOIDLEMSG)
                 dwFlags |= MLF_NOIDLEMSG;
                VERIFY(RunModalLoop(dwFlags) == m_nModalResult);//這里是真正的循環RunModalLoop
               }

               // hide the window before enabling the parent, etc.
               if (m_hWnd != NULL)
                SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW|
                 SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
              }
             }
             CATCH_ALL(e)
             {
              DELETE_EXCEPTION(e);
              m_nModalResult = -1;
             }
             END_CATCH_ALL

             if (bEnableParent)
              ::EnableWindow(hWndParent, TRUE);
             if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd)
              ::SetActiveWindow(hWndParent);

             // destroy modal window
             DestroyWindow();
             PostModal();

             // unlock/free resources as necessary
             if (m_lpszTemplateName != NULL || m_hDialogTemplate != NULL)
              UnlockResource(hDialogTemplate);
             if (m_lpszTemplateName != NULL)
              FreeResource(hDialogTemplate);

             return m_nModalResult;
            }

            模式對話框調用的循環函數RunModalLoop()函數如下:
            int CWnd::RunModalLoop(DWORD dwFlags)
            {
             ASSERT(::IsWindow(m_hWnd)); // window must be created
             ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state

             // for tracking the idle time state
             BOOL bIdle = TRUE;
             LONG lIdleCount = 0;
             BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
             HWND hWndParent = ::GetParent(m_hWnd);
             m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
             MSG* pMsg = &AfxGetThread()->m_msgCur;

             // acquire and dispatch messages until the modal state is done
             for (;;)
             {
              ASSERT(ContinueModal());

              // phase1: check to see if we can do idle work
              while (bIdle &&
               !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
              {
               ASSERT(ContinueModal());

               // show the dialog when the message queue goes idle
               if (bShowIdle)
               {
                ShowWindow(SW_SHOWNORMAL);
                UpdateWindow();
                bShowIdle = FALSE;
               }

               // call OnIdle while in bIdle state
               if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
               {
                // send WM_ENTERIDLE to the parent
                ::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
               }
               if ((dwFlags & MLF_NOKICKIDLE) ||
                !SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
               {
                // stop idle processing next time
                bIdle = FALSE;
               }
              }

              // phase2: pump messages while available
              do
              {
               ASSERT(ContinueModal());

               // pump message, but quit on WM_QUIT
               if (!AfxGetThread()->PumpMessage())//主要在這里循環
               {
                AfxPostQuitMessage(0);
                return -1;
               }

               // show the window when certain special messages rec'd
               if (bShowIdle &&
                (pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
               {
                ShowWindow(SW_SHOWNORMAL);
                UpdateWindow();
                bShowIdle = FALSE;
               }

               if (!ContinueModal())
                goto ExitModal;

               // reset "no idle" state after pumping "normal" message
               if (AfxGetThread()->IsIdleMessage(pMsg))
               {
                bIdle = TRUE;
                lIdleCount = 0;
               }

              } while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
             }

            ExitModal:
             m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
             return m_nModalResult;
            }

            一般程序調用的循環函數Run函數如下:
            int CWinThread::Run()
            {
             ASSERT_VALID(this);

             // for tracking the idle time state
             BOOL bIdle = TRUE;
             LONG lIdleCount = 0;

             // acquire and dispatch messages until a WM_QUIT message is received.
             for (;;)
             {
              // phase1: check to see if we can do idle work
              while (bIdle &&
               !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
              {
               // call OnIdle while in bIdle state
               if (!OnIdle(lIdleCount++))
                bIdle = FALSE; // assume "no idle" state
              }

              // phase2: pump messages while available
              do
              {
               // pump message, but quit on WM_QUIT
               if (!PumpMessage())
                return ExitInstance();

               // reset "no idle" state after pumping "normal" message
               if (IsIdleMessage(&m_msgCur))
               {
                bIdle = TRUE;
                lIdleCount = 0;
               }

              } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
             }

             ASSERT(FALSE);  // not reachable
            }

            ==========
            我認為是更加完整的應該是_DllMainCRTStartup-> WinMainCRTStartup(void)->()->_tWinMain(開始)->AfxWinMain(開始)->AfxGetThread()->AfxWinInit()->InitApplication()->InitInstance()->DoModal()->RunModalLoop()->ExitInstance()->AfxWinMain(結束)->_tWinMain(結束)

            參考http://www.shnenglu.com/citywanderer/articles/8716.html
            posted on 2009-10-01 22:51 鷹擊長空 閱讀(1595) 評論(0)  編輯 收藏 引用
            精品久久久久香蕉网| 久久丫忘忧草产品| 国产巨作麻豆欧美亚洲综合久久 | 91精品婷婷国产综合久久| 欧美久久综合性欧美| 亚洲欧美一级久久精品| 久久久无码精品亚洲日韩蜜臀浪潮 | 久久91亚洲人成电影网站| 久久久久亚洲av毛片大| 囯产精品久久久久久久久蜜桃| 国产成人综合久久综合| 久久精品国产亚洲av麻豆蜜芽| 国产精品欧美久久久天天影视| 亚洲欧美精品一区久久中文字幕 | 久久精品国产亚洲一区二区三区 | 国产成人久久777777| 亚洲午夜无码久久久久| 久久99精品久久久久久齐齐| 亚洲AV无一区二区三区久久 | 国内精品久久久久影院亚洲| 亚洲午夜久久久精品影院| 国产精品99久久久精品无码 | 日韩精品久久久久久| 中文字幕乱码久久午夜| 大香伊人久久精品一区二区 | 久久人妻少妇嫩草AV无码蜜桃| 人妻无码αv中文字幕久久琪琪布 人妻无码久久一区二区三区免费 人妻无码中文久久久久专区 | 亚洲午夜久久久精品影院| 久久精品中文无码资源站| 久久久精品人妻一区二区三区蜜桃| 久久精品这里只有精99品| 国产精品VIDEOSSEX久久发布| 国产精品对白刺激久久久| 久久久久无码精品国产| 国产精品女同久久久久电影院| 亚洲AV无码久久寂寞少妇| 精品久久久久久中文字幕大豆网| 日韩欧美亚洲综合久久| 国产成人精品久久| 国产精品对白刺激久久久| 91亚洲国产成人久久精品|