开发者

Assertion Error in Dialog manipulation

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, (LP开发者_如何学JAVAARAM)lpszString); }

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

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


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


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


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().


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜