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


    从代码分析原因吧:

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

    // main running routine until thread exits
    int 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 first
    
    int 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
    ");
                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).
    ",
                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, "警告: 对话框创建失败,应用程序将意外终止。
    ");
            TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。
    ");
        }
    
        // 删除上面创建的 shell 管理器。
        if (pShellManager != NULL)
        {
            delete pShellManager;
        }
    
        // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
        //  而不是启动应用程序的消息泵。
        return FALSE;
    }

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

  • 相关阅读:
    解决首次访问jenkins,输入初始化默认密码之后,一直卡住问题,无法进行jenkins工具安装
    tomcat下安装jenkins
    主机无法访问虚拟机Linux的apache
    Centos 6.5 yum 安装Apache软件
    Linux如何用yum安装软件或服务
    linux yum安装httpd后,启动service httpd start 报错解决方案
    Thrift白皮书阅读笔记
    利用thrift在c++、java和python之间相互调用
    [原]Windows下openssl的下载安装和使用
    Windows 下openssl安装与配置
  • 原文地址:https://www.cnblogs.com/shanql/p/6597094.html
Copyright © 2020-2023  润新知