对话框操作中的断言错误

Assertion Error in Dialog manipulation

本文关键字:断言 错误 操作 对话框      更新时间:2023-10-16

标题很弱,但我会尝试在这里解释。我正在开发一个 MFC 应用程序。单击按钮时,将创建一个新对话框,将一些字符串从第二个对话框添加到ComboBox,然后显示该对话框。代码如下所示。Combo1 是在 Class1.h 文件中定义的CComboBox变量。问题是当我尝试调用dlg.Foo()方法时,程序给了我一个Debug Assertion Error。错误出现在AddString行上,此外,在afxwin2.inl文件中,在以下代码行中:

{ ASSERT(::IsWindow(m_hWnd)); return (int)::SendMessage(m_hWnd, CB_ADDSTRING, 0, (LPARAM)lpszString); }

CClass1 dlg = new CClass1(this);
dlg.Foo();
dlg.DoModal();

void CClass1::Foo()
{
    Combo1.AddString(TEXT("text"));
}

您可以将字符串添加到 OnInitDialog(( 中的组合框中,该组合框在 DoModal(( 期间自动调用:

在标题中:

class CClass1 : public CDialog
{
    protected:
        virtual BOOL OnInitDialog();
}

在 cpp 文件中:

BOOL CClass1::OnInitDialog()
{
    __super::OnInitDialog();
    Combo1.AddString(TEXT("text"));  // or just call Foo() here if that's preferred
    return TRUE;
}

在调用 foo(( 时尚未创建组合框窗口。您可能希望将 CStringArray 成员添加到 CClass1,然后将其设置为使用 DDX 加载组合框。DDX 步骤将在创建组合框窗口后发生。

下面是一个自定义 DDX 函数,它完全可以执行此任务:

void AFXAPI 
DDX_CBStringArray (CDataExchange* pDX, int nIDC, CStringArray& strings)
{
    HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
    bool bMine = false;
    CComboBox* pCB = dynamic_cast<CComboBox*>(CWnd::FromHandlePermanent(hWndCtrl));
    if (!pCB)
    {
        pCB = new CComboBox;
        pCB->Attach(hWndCtrl);
        bMine = true;
    }
    if (pDX->m_bSaveAndValidate)
    {
        strings.RemoveAll();
        int nNumStrings = pCB->GetCount();
        CString strVal("");
        for (int x = 0; x < nNumStrings; ++x)
        {
            pCB->GetLBText(x, strVal);
            strings.Add(strVal);
        }
    }
    else
    {
        pCB->ResetContent();
        INT_PTR nSize = strings.GetSize();
        for (INT_PTR x = 0; x < nSize; ++x)
        {
            pCB->AddString(strings.GetAt(x));
        }
    }
    if (bMine)
    {
        pCB->Detach();
        delete pCB;
    }
}

您将向 CClass1 添加一个 CStringArray 成员,并在 DDX 块中添加对此函数的引用。在构造类实例之后,但在调用 DoModal(( 之前,将 ComboBox 中所需的字符串添加到 StringArray 变量中。此功能将为您填充组合框。

CClass1 更改如下:

CClass1 : public CDialogEx
{
...
public:
    CStringArray myStringEntries;
...
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
...
};

您的 DoDataExchange 覆盖将如下所示:

void CClass1::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CClass1)
    DDX_CBStringArray(pDX, IDC_COMBO1, myStringEntries);
    ...
    //}}AFX_DATA_MAP
}

您的调用类更改为:

CClass1 dlg(this);
dlg.myStringEntries.Add("Some text");
dlg.myStringEntries.Add("More text");
dlg.DoModal();

或者,也可以更改 CClass1::foo(( 以填充 CStringArray:

void CClass1::Foo()
{
    myStringEntries.Add(TEXT("text"));
    myStringEntries.Add(TEXT("more text"));
}

嘿! 我有一个建议,有一种更简单的方法可以将字符串从第一个对话框传递到第二个对话框。您已经在第一个对话框中创建了第二个对话框类的实例,现在您需要做的就是将一个字符串成员变量添加到第二个对话框的类中,并在调用 DoModal(( 之前使用 combobox 字符串初始化此变量。

当您在OnInitDialog函数中引用m_comboBox时,即使DoDataExchange定义中存在m_comboBox,您也会得到错误。

您可以通过两种方法解决此问题:

  1. 在您的OnInitDialog中,您可以使用以下方法引用您的组合框

    CComboBox *cmb = (CComboBox *(GetDlgItem(IDC_YOURCOMBOBOX(;

  2. 或在访问 m_comboBox 之前调用 UpdateData ,这将调用 DoDataExchange 函数,如 MSDN 文档中有关DoDataExchange函数的备注中所述。