对话框操作中的断言错误

发布于 2024-11-11 16:38:50 字数 594 浏览 4 评论 0原文

标题很弱,但我会在这里尝试解释一下。我正在开发 MFC 应用程序。单击按钮时,将创建一个新对话框,将一些字符串添加到第二个对话框中的 ComboBox 中,然后显示该对话框。代码如下所示。 Combo1 是 Class1.h 文件中定义的一个 CComboBox 变量。问题是,当我尝试调用 dlg.Foo() 方法时,程序给我一个调试断言错误。错误出现在 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"));
}

The title is pretty weak, but I will try to explain here. I am working on an MFC Application. When a button is clicked, a new dialog is created, some strings are added to a ComboBox from that second dialog, and then the dialog is showed. The code is depicted below. Combo1 is a CComboBox variable defined in the Class1.h file. The problem is that when I try to call the dlg.Foo() method, the program gives me a Debug Assertion Error. The error hits on the AddString line, furthermore in the afxwin2.inl file, in this line of code:

{ 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"));
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

燕归巢 2024-11-18 16:38:50

您可以将字符串添加到 内的组合框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;
}

You can add the strings to the combo box inside of OnInitDialog(), which gets called automatically during DoModal():

In the header:

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

In the cpp file:

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

    return TRUE;
}
心如荒岛 2024-11-18 16:38:50

在您调用 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"));
}

The combobox window has not been created at the point you're calling foo(). You probably want to add a CStringArray member to CClass1, and then set it up to use DDX to load the combobox. The DDX step will happen AFTER the combobox window is created.

Here's a custom DDX function that does exactly this task:

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;
    }
}

You will add a CStringArray member to CClass1, and add a reference to this function in your DDX block. You add the strings you want in your ComboBox into the StringArray variable after you construct the class instance, but before you call DoModal(). This function will populate the combo box for you.

CClass1 is changed like so:

CClass1 : public CDialogEx
{
...
public:
    CStringArray myStringEntries;

...
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
...
};

Your DoDataExchange override will look like:

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

Your calling class changes to:

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

Or, alternatively, CClass1::foo() can be changed to populate the CStringArray:

void CClass1::Foo()
{
    myStringEntries.Add(TEXT("text"));
    myStringEntries.Add(TEXT("more text"));
}
蘑菇王子 2024-11-18 16:38:50

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

Hey! i have one suggestion, there is a simpler way of passing the string from the first dialog to the second. You have already created an instance of the second dialog's class in the first dialog, now all you need to do is add a string member variable to the second dialog's class and initalize this variable with the combobox string before calling DoModal().

鹿童谣 2024-11-18 16:38:50

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

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

  1. OnInitDialog 中,您可以使用以下命令引用组合框

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

  2. 或者在访问m_comboBox之前调用UpdateData,这将调用DoDataExchange函数,如有关 DoDataExchange 函数的 MSDN 文档

When you refer to an m_comboBox in your OnInitDialog function you will get an error even if m_comboBox is present in the DoDataExchange definition.

You can solve this with two methods:

  1. In your OnInitDialog you can refer to your combobox with

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

  2. or call UpdateData before accessing m_comboBox, which will call the DoDataExchange function as explained in the remarks of MSDN documentation about the DoDataExchange function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文