Instantiating a dialog in a Doc function, I can update an Edit box in the dialog, but when I try to use AddString on a Listbox (using "simple text"), I get an Assertion Failure.
Using VC++6; to illustrate the problem in the simplest app, I created an SDI Doc/View app, added a Dialog class, added a new menu item to invoke the dialog, then added an Editbox (with member variable)and a CListbox (with control member variable) to the dialog. The fact that I can write to the Editbox suggests that the invocation of the Dialog is ok, but the Assertion Error for the List box is a puzzle. I can add data using AddString in an InitDialog function, but this is useless, since I want to add data to the ListBox at runtime. Must be a simple omission somewhere........
In the .inl file at Line 668/669 is:
[668] _AFXWIN_INLINE int CListBox::AddString(LPCTSTR lpszItem)
[669] { ASSERT(::IsWindow(m_hWnd)); return (int)::SendMessage(m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszItem); }
As I wrote earlier, a statement which writes to an Edit Box on the Dialog form is successful, whereas a trying to AddString to the List Box at the same point in the function which instantiates the Dialog causes the Assertion failure. Looks to me like the CListBox::AddString command is expecting to find the Dialog in a standard place, rather than actually getting it from the instantiated Dlg. (Excuse my poor jargonese).
May be you are missing DDX entry for the control or string. Please check if the variable name is present in your MESSAGE_MAP macro. Also, see to it that OnInitialUpdate() function calls the base class version in your view class.
Regards,
Bhushan
Thanks for reply, bhushan.
The Dialog class has a DDX entry for the ListBox (c_list):
void CDlg:oDataExchange(CDataExchange* pDX)
{
CDialog:oDataExchange(pDX);
//{{AFX_DATA_MAP(CDlg)
DDX_Control(pDX, IDC_LIST1, c_list);
DDX_Text(pDX, IDC_EDIT1, m_edit1);
//}}AFX_DATA_MAP
}
The MESSAGE_MAP for the entire Dialog class is empty. I would never guess in a million years what to put there, nor why.
I also cannot guess what to put in View::OnInitialUpdate.
This c**p drives me mad.
I should add that I want to access the ListBox from the Doc: that's where the data is.
I'll also repeat the point: I can write to the EditBox in the dialog from a Doc function, but attempting to access the CListBox of the Dialog causes an assertion error. It is clear that the Doc class doesn't have a clue about the CListBox, but how to get round this? Or any suggestions as to how to present the user with a list of runtime-generated items, from which they can select any or all? Where in any MS info is there any reference to the need to hand crank a CListBox into life (other than when it's embedded in a CDialog-based appplication)? Maybe I need to use the dreaded GetDlgItem(..) ?
I should add that I want to access the ListBox from the Doc: that's where the data is.
I'll also repeat the point: I can write to the EditBox in the dialog from a Doc function, but attempting to access the CListBox of the Dialog causes an assertion error. It is clear that the Doc class doesn't have a clue about the CListBox, but how to get round this?
Your problem is in your design. You shouldn't access dialog controls from your doc, you should access data from your dialog. You can either pass the data from the doc to the dialog before you create it, or you can give the dialog a pointer to your doc and let the dialog ask for the information.
Maybe I need to use the dreaded GetDlgItem(..) ?
What's dreaded about GetDlgItem?
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
This is a doc/view app. The app reads in a few Mb from various data files (1 to many), and converts and displays the data. The user must be given the choice of which of the various data sets to display together. Therefore a dialog needs to be invoked, in order to present a listbox identifying the data sets which are in memory. All the data is at that point in the Doc. The ListBox has to present the choices, but obviously has to access the identities of the data sets. So I need to pass some info from the Doc to the Dialog. The data is not pre-existing in the dialog, and this is not a dialog app.
You wrote:
"You can ... pass the data from the doc to the dialog before you create it".
That is what I am trying to do, and that is the problem!
I can indeed write to an EditBox in the dialog which I instantiate in a Doc function, but when I try to get the Listbox to accept data (AddString(..)) in the same function, a Windows Assertion Failure is generated. Therefore the ClistBox appears not to have been initialised or its pointer is bent. So there is something tricky about a CListBox in a dialog which is not part of a Dialog-based application.
This is a doc/view app. The app reads in a few Mb from various data files (1 to many), and converts and displays the data. The user must be given the choice of which of the various data sets to display together. Therefore a dialog needs to be invoked, in order to present a listbox identifying the data sets which are in memory. All the data is at that point in the Doc. The ListBox has to present the choices, but obviously has to access the identities of the data sets. So I need to pass some info from the Doc to the Dialog. The data is not pre-existing in the dialog, and this is not a dialog app.
You wrote:
"You can ... pass the data from the doc to the dialog before you create it".
That is what I am trying to do, and that is the problem!
I can indeed write to an EditBox in the dialog which I instantiate in a Doc function, but when I try to get the Listbox to accept data (AddString(..)) in the same function, a Windows Assertion Failure is generated. Therefore the ClistBox appears not to have been initialised or its pointer is bent. So there is something tricky about a CListBox in a dialog which is not part of a Dialog-based application.
This doesn't have anything to do with the architecture. Most likely you are trying to access the CListBox.Addstring before calling the base class O
Code:
BOOL CMyDlg::OnInitDialog()
{
// BUG: Don't make any calls to child controls here
CDialog::OnInitDialog();
// Child controls initialized, okay to make controls here.
...
}
By the way, passing the data to the dialog is fairly simple. I usually just pass in a pointer to the document in the dialog's constructor.
Just add a parameter to the default dlg constructor that takes your specific app document pointer.
It's not that it's dreaded, it's just that using it results in extra code.
IMO, most folks use GetDlgItem because it's a carry over from coding in Win32 or they don't know how to create a Control variable in MFC.
The DDX mechanism hides the GetDlgItem implementation, when using data variables also handles the data transfer between the control and its associated variable.
Rather than having ugly GetDlgItem calls with casting everywhere, you can just use the dialog control variable.
Consider an edit box and say you want to hide it.
Create a control variable, and then...
Code:
m_EditBox.ShowWindow( SW_HIDE );
What about setting the edit box string?
Create a value variable (like CString), and then...
Sure, you can argue that they're both 2 lines. But consider that UpdateData( ) only needs to be called once after setting any values - even for multiple controls.
GCDEF, yes , thanks for the reminder. And I did notice that nice row of medals you've got there. Now, what about a suggestion, or is putting a usable listbox in a dialog called from a menu entry in a doc/view app really complex? If I knew the solution, I wouldn't be posting here btw.
GCDEF, yes , thanks for the reminder. And I did notice that nice row of medals you've got there. Now, what about a suggestion, or is putting a usable listbox in a dialog called from a menu entry in a doc/view app really complex? If I knew the solution, I wouldn't be posting here btw.
The point is the listbox has to exist when you add strings to it. It exists after the call in OnInitDialog to CDialog::OnInitDialog, and before CDialog::EndDialog gets called, which usually happens when you press the okay or cancel buttons.
Can you post a small snipped that shows how you're adding strings and from where.
This is pretty basic. I've created a VC++ 2005 project to show one approach. This sample opens a test dialog from the view and passes in the pointer to the document. However, the test dialog could be as easily invoked from the mainframe or document as well.
I've added a m_sEdit variable to the document and a public GetEditString() public accessor method.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.