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:
In your
OnInitDialog
you can refer to your combobox withCComboBox *cmb = (CComboBox *)GetDlgItem(IDC_YOURCOMBOBOX);
or call
UpdateData
before accessingm_comboBox
, which will call theDoDataExchange
function as explained in the remarks of MSDN documentation about theDoDataExchange
function.
精彩评论