• <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
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(2)

            隨筆檔案

            文章檔案

            網(wǎng)頁收藏

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

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

            1、KERNEL32
            kernel32.dll是Windows9x/Me中非常重要的32位動(dòng)態(tài)鏈接庫文件,屬于內(nèi)核級(jí)文件。它控制著系統(tǒng)的內(nèi)存管理、數(shù)據(jù)的輸入輸出操作和中斷處理,當(dāng)Windows啟動(dòng)時(shí),kernel32.dll就駐留在內(nèi)存中特定的寫保護(hù)區(qū)域,使別的程序無法占用這個(gè)內(nèi)存區(qū)域。

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

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

            4、AfxWinMain()函數(shù)
            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()函數(shù)
            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()函數(shù)
            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() 函數(shù)
            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()函數(shù)
            AfxWinMain函數(shù)里面的if (!pThread->InitInstance())會(huì)調(diào)用程序CMy1App的InitInstance函數(shù):
            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;//調(diào)用CMy1Dlg的構(gòu)造函數(shù)
             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()函數(shù)里面的主要的循環(huán)體,在這里:
                    if (!pThread->InitInstance())//主要是模式對(duì)話框調(diào)用,對(duì)話框關(guān)閉以后InitInstance函數(shù)才會(huì)結(jié)束
             {
              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();//非模式對(duì)話框和一般程序調(diào)用這個(gè)循環(huán)

            InitInstance函數(shù)調(diào)用了dlg.DoModal()函數(shù),以下是DoModal()函數(shù):
            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))//創(chuàng)建對(duì)話框的窗口
              {
               if (m_nFlags & WF_CONTINUEMODAL)
               {
                // enter modal loop
                DWORD dwFlags = MLF_SHOWONIDLE;
                if (GetStyle() & DS_NOIDLEMSG)
                 dwFlags |= MLF_NOIDLEMSG;
                VERIFY(RunModalLoop(dwFlags) == m_nModalResult);//這里是真正的循環(huán)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;
            }

            模式對(duì)話框調(diào)用的循環(huán)函數(shù)RunModalLoop()函數(shù)如下:
            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())//主要在這里循環(huán)
               {
                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;
            }

            一般程序調(diào)用的循環(huán)函數(shù)Run函數(shù)如下:
            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
            }

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

            參考http://www.shnenglu.com/citywanderer/articles/8716.html
            posted on 2009-10-01 22:51 鷹擊長空 閱讀(1594) 評(píng)論(0)  編輯 收藏 引用

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            亚洲精品无码成人片久久| 国内精品九九久久久精品| 久久99热只有频精品8| 亚洲?V乱码久久精品蜜桃| 国产综合成人久久大片91| 久久99国产精品成人欧美| 久久综合久久综合久久| 99久久国产亚洲高清观看2024| 久久精品成人免费观看97| 精品熟女少妇AV免费久久| 午夜天堂av天堂久久久| 漂亮人妻被黑人久久精品| 久久久艹| 久久精品中文无码资源站| 精品人妻伦九区久久AAA片69| 久久精品国产2020| 久久精品亚洲一区二区三区浴池| 久久久久国产精品熟女影院| 偷窥少妇久久久久久久久| 久久久免费精品re6| 99久久免费国产精精品| 精品久久久久久久久久中文字幕| 国产69精品久久久久99| 精品熟女少妇AV免费久久 | 人妻无码久久一区二区三区免费| 亚洲中文久久精品无码| 精品久久香蕉国产线看观看亚洲| 亚洲精品成人网久久久久久| 精品久久久久香蕉网| 99热精品久久只有精品| 久久亚洲国产精品五月天婷| 美女久久久久久| 久久国产精品无码网站| 亚洲国产精品无码久久一线| 国产一级持黄大片99久久 | 青青草原综合久久大伊人精品| 青青草国产精品久久久久| 久久久久久国产精品无码下载| 国产人久久人人人人爽| 日日狠狠久久偷偷色综合免费 | 青青国产成人久久91网|