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

            隨筆檔案

            文章檔案

            網頁收藏

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            例子是一個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 鷹擊長空 閱讀(1594) 評論(0)  編輯 收藏 引用
            伊人久久无码中文字幕| 欧美性猛交xxxx免费看久久久| 狠狠色婷婷久久综合频道日韩| 久久天天躁狠狠躁夜夜不卡| 亚洲综合伊人久久大杳蕉| 国产美女久久精品香蕉69| 91久久精品电影| 色诱久久久久综合网ywww| 欧美久久精品一级c片片| 久久亚洲精品国产精品婷婷| 久久99精品久久久久久| 精品久久久久久久久免费影院| 天天综合久久久网| 97久久婷婷五月综合色d啪蜜芽| 久久香蕉国产线看观看99| 国产aⅴ激情无码久久| 久久亚洲AV永久无码精品| 国产成人久久精品激情| 午夜视频久久久久一区 | 国产成人无码精品久久久久免费 | 亚洲AV无码久久精品狠狠爱浪潮| 久久亚洲综合色一区二区三区| 国内精品九九久久精品| 久久久久亚洲精品无码网址 | 久久99精品综合国产首页| 亚洲中文字幕无码久久精品1| 久久久久无码国产精品不卡| 久久精品国产亚洲沈樵| 久久精品无码专区免费青青 | 国产99久久久国产精免费| 久久国产欧美日韩精品| 久久亚洲AV成人无码国产| 偷偷做久久久久网站| 国产99精品久久| 久久久一本精品99久久精品66 | 国产精品久久久久9999高清| 婷婷伊人久久大香线蕉AV | 亚洲国产精品无码久久SM| 亚洲国产成人久久综合一区77| 久久精品国产亚洲7777| 久久人人爽人人精品视频|