【问题标题】:MFC, EndDialog, repeated dialog creation causes unexpected behaviorMFC、EndDialog、重复对话框创建导致意外行为
【发布时间】:2013-01-18 01:35:03
【问题描述】:

我需要根据其大小动态调整对话窗口。为此,我采用了以下技术:

  1. 我加载它并从 CDialog::OnInitDialog() 处理程序中获取它的大小。

  2. 如果尺寸太大,我通过调用 CDialog::EndDialog 来结束对话框

  3. 然后更新全局变量并通过大小调整再次重新初始化对话框派生类。

发生的情况是,在第二次通过时,一些 API 开始出现异常行为。例如,MessageBox 不显示(因此所有 ASSERT 宏都停止工作)并且某些 SetWindowText API 使应用程序崩溃。知道为什么吗?

这里是sn-ps的代码:

#define SPECIAL_VALUE -1
//From CWinApp-derived class
BOOL CWinAppDerivedClass::InitInstance()
{
    //...

    for(;;)
    {
        CDialogDerivedClass dlg(&nGlobalCounter);
        m_pMainWnd = &dlg;
        if(dlg.DoModal() != SPECIAL_VALUE)
            break;
    }

    //...
}

然后从对话框类本身:

//From CDialogDerivedClass
BOOL CDialogDerivedClass::OnInitDialog()
{
    //The following API shows message box only on the 1st pass, why?
    ::MessageBox(NULL, L"1", L"2", MB_OK);

    //...

    if(checkedDialogSizeIndicatesReload)
    {
        this->EndDialog(SPECIAL_VALUE);
        return FALSE;
    }

    //Continue loading dialog as usual
    ...
}

编辑:我偶然注意到,如果我注释掉以下行,它似乎可以工作。知道为什么吗?

//m_pMainWnd = &dlg;

【问题讨论】:

  • 因为 m_pMainWnd 是主窗口。为了使您的方案正常工作,您最好提供另一个隐藏的 CWnd 作为主窗口。
  • 我猜测并说这是因为 dlg 超出范围而留下了一个悬空指针。尝试在 DoModal 返回后将 m_pMainWnd 设置为 NULL。
  • @TheSteve:不,那不行。仅当我在上面的代码 sn-p 之后从 OnInitDialog 中执行 theApp.m_pMainWnd = this; 时,它才有效。但它也可以通过简单地注释该行来工作。我仍然不清楚m_pMainWnd 的目的,MSDN 也没有多大帮助......

标签: c++ windows winapi mfc dialog


【解决方案1】:

变量dlg在你设置m_pMainWnd的地方还不是一个窗口(对话框只有在OnInitInstance返回TRUE后才显示);以下代码应该可以工作:

for(;;)
{
    CDialogDerivedClass dlg(&nGlobalCounter);
//  m_pMainWnd = &dlg;
    if(dlg.DoModal() != SPECIAL_VALUE)
        break;
}
m_pMainWnd = &dlg;

【讨论】:

    【解决方案2】:

    InitDialog 是对话框窗口出现在屏幕上之前处理的最后一条消息 - 您可以检测和调整大小,而不是您正在做的那种时髦的全局变量。

    if(checkedDialogSizeIndicatesReload)
        {
        // look up SetWindowPos - 
        // I am nt sure if there is another parameter or not that is optional
        int x,y,cx,cy;
        WINDOWPLACEMENT wp;
        GetWindowPlacement(&wp);
        // calc new size here
        SetWindowPos(this,x,y,cx,cy);
        }
    
    // window appears when the message handler returns
    

    【讨论】:

    • 不,没那么简单。我对我的原始帖子进行了编辑。你知道为什么m_pMainWnd 会有所作为吗?
    • 它可能只是“似乎有效”。正确的技术是按照 ahmd0 的建议调整 OninitDialog 处理程序中的大小。
    • 就是我说的,把他的大小调整逻辑移到InitDialog中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-27
    • 2011-02-13
    • 1970-01-01
    • 2011-03-16
    • 2015-06-30
    • 1970-01-01
    相关资源
    最近更新 更多