MFC模态对话框程序不响应OnIdle

来源:互联网 发布:文学常识软件 编辑:程序博客网 时间:2024/04/28 05:52
从代码分析原因吧:

 

OnIdle函数在MFC的CWinThread::Run函数中被调用,如下

// main running routine until thread exitsint CWinThread::Run(){    ASSERT_VALID(this);    _AFX_THREAD_STATE* pState = AfxGetThreadState();    // 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(&(pState->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))            if (IsIdleMessage(&(pState->m_msgCur)))            {                bIdle = TRUE;                lIdleCount = 0;            }        } while (::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE));    }}

 

CWinThread::Run又在AfxWinMain中被调用,

/////////////////////////////////////////////////////////////////////////////// Standard WinMain implementation//  Can be replaced as long as 'AfxWinInit' is called firstint AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,    _In_ 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)        {            TRACE(traceAppMsg, 0, "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)    {        TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n",            AfxGetModuleThreadState()->m_nTempMapLock);    }    AfxLockTempMaps();    AfxUnlockTempMaps(-1);#endif    AfxWinTerm();    return nReturnCode;}

要运行CWinThread::Run,则需要pThread->InitInstance返回才行,但模态对话框程序有点特殊,会直接阻塞在DoMoDal函数中,然后运行自己的消息循环(代码如下),CXXXApp::InitInstace在程序没结束时,不会返回,故OnIdle不会得到运行

BOOL CXXXApp::InitInstance(){    // 如果一个运行在 Windows XP 上的应用程序清单指定要    // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,    //则需要 InitCommonControlsEx()。否则,将无法创建窗口。    INITCOMMONCONTROLSEX InitCtrls;    InitCtrls.dwSize = sizeof(InitCtrls);    // 将它设置为包括所有要在应用程序中使用的    // 公共控件类。    InitCtrls.dwICC = ICC_WIN95_CLASSES;    InitCommonControlsEx(&InitCtrls);    CWinApp::InitInstance();    AfxEnableControlContainer();    // 创建 shell 管理器,以防对话框包含    // 任何 shell 树视图控件或 shell 列表视图控件。    CShellManager *pShellManager = new CShellManager;    // 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));    // 标准初始化    // 如果未使用这些功能并希望减小    // 最终可执行文件的大小,则应移除下列    // 不需要的特定初始化例程    // 更改用于存储设置的注册表项    // TODO: 应适当修改该字符串,    // 例如修改为公司或组织名    SetRegistryKey(_T("应用程序向导生成的本地应用程序"));    CXXXDlg dlg;    m_pMainWnd = &dlg;    INT_PTR nResponse = dlg.DoModal();    if (nResponse == IDOK)    {        // TODO: 在此放置处理何时用        //  “确定”来关闭对话框的代码    }    else if (nResponse == IDCANCEL)    {        // TODO: 在此放置处理何时用        //  “取消”来关闭对话框的代码    }    else if (nResponse == -1)    {        TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");        TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");    }    // 删除上面创建的 shell 管理器。    if (pShellManager != NULL)    {        delete pShellManager;    }    // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,    //  而不是启动应用程序的消息泵。    return FALSE;}

由代码可知,MFC的模态对话框程序的OnIdle函数是不会被调用到的

0 0
原创粉丝点击