Ошибка утверждения в манипуляциях с диалогом - PullRequest
3 голосов
/ 01 июня 2011

Название довольно слабое, но я постараюсь объяснить здесь.Я работаю над приложением MFC.При нажатии кнопки создается новое диалоговое окно, некоторые строки добавляются в ComboBox из этого второго диалогового окна, а затем отображается диалоговое окно.Код изображен ниже.Combo1 - это переменная CComboBox, определенная в файле Class1.h.Проблема в том, что когда я пытаюсь вызвать метод 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"));
}

Ответы [ 4 ]

4 голосов
/ 01 июня 2011

Вы можете добавить строки в поле со списком внутри 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;
}
2 голосов
/ 01 июня 2011

Окно со списком не было создано в точке, которую вы вызываете 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;
    }
}

Вы добавите элемент CStringArray в CClass1 и добавитессылка на эту функцию в вашем блоке DDX.Вы добавляете нужные вам строки в свой ComboBox в переменную StringArray после создания экземпляра класса, но перед вызовом DoModal ().Эта функция заполнит поле со списком для вас.

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"));
}
0 голосов
/ 16 января 2015

Когда вы ссылаетесь на m_comboBox в вашей функции OnInitDialog, вы получите ошибку, даже если m_comboBox присутствует в определении DoDataExchange.

Вы можете решить эту проблему двумя способами:

  1. В вашем OnInitDialog вы можете обратиться к вашему списку с помощью

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

  2. или позвоните UpdateData перед доступом к m_comboBox, что вызовет функцию DoDataExchange, как объяснено в примечаниях Документация MSDN о функции DoDataExchange.

0 голосов
/ 01 июня 2011

Эй! У меня есть одно предложение, есть более простой способ передачи строки из первого диалога во второй. Вы уже создали экземпляр класса второго диалогового окна в первом диалоговом окне, и теперь все, что вам нужно сделать, это добавить переменную-член строки в класс второго диалогового окна и инициализировать эту переменную строкой со списком перед вызовом DoModal ().

...