Once this is entered, I want to ask the following questions:
Age:
Name:
Height:
So say the user enters 20 people, I need to ask for the above details 20 times?
Because I don’t know how many people the user will enter I cannot create all the edit boxes for this before so what’s the best programming/practical way to do this?
I am sorry if this is such a basic question but I am just learning MFC and I’m not sure how this can be done. Because from what I know so far if I create an edit box I can only attach one variable (which threw my idea of using arrays out the window) to it…so does that mean I need 20 different edit boxes.
Please can anyone offer any advise or direct me in the right path!
Last edited by Ankoump; January 8th, 2004 at 06:26 AM.
This is a more a question of Windows user interface design, rather than MFC.
For a list of items, I would use a list box (CListBox) or list control (CListCtrl). Stick to CListBox for now - it is simpler to use.
So on your main dialog, put a CListBox, with Add, Edit and Delete buttons below it (or where ever you fancy). Each line in the list box is a different person.
Add and Edit bring up a child dialog where you can add a new person (Name, Age, Height etc). Use the same dialog for both Add and Edit. If editing, then prepopulate with the details of the person currently selected in the list box.
Delete simply deletes the currently selected line in the list box.
All this is pretty easy to do in MFC, but I fear may be a bit advanced for a beginner. I suggest you keep doing the tutorials, reading the text books.
Thanks a lot for that…I will try this method .
However, I just wanted to find out how with this method each person (represented by an item in the list box) has their age etc associated with them, if I am using the same child dialog to add people.
Well, this is where it gets a (little) bit clever.
Create a class to represent people, e.g., CPerson. The class should have properties for each bit of data about the person, e.g., name, age, height etc. Each person (row) in the list box is an object of this class. Use CListBox::SetItemDataPtr to associate the row in the list box with the person object for that row.
Something like this (CPersonDlg is your popup child dialog):
Code:
OnAdd:
CPersonDlg PersonDlg;
if (PersonDlg.DoModal() == IDOK)
{
// OKed from child dialog, so add new person to list box.
int nIndex = m_myListBox.AddString(PersonDlg.m_sPersonName);
if (nIndex != LB_ERR && nIndex != LB_ERRSPACE)
{
// New person successfully added to list box, so create a person object for them, using
// the member variables from the child dialog.
CPerson* pPerson = new CPerson(PersonDlg.m_sPersonName, PersonDlg.m_nSex, PersonDlg.m_DataOfBirth);
if (pPerson != NULL)
{
// Associate the new person object with the row in the list box.
m_myListBox.SetItemDataPtr(nIndex, pPerson);
}
}
}
OnEdit:
int nIndex = m_myListBox.GetCurSel();
if (nIndex != LB_ERR)
{
// Row is selected in list box, so get person object for this row, and pass to
// contructor for child dialog.
CPerson* pPerson = m_myListBox.GetItemDataPtr(nIndex);
if (pPerson != NULL)
{
CPersonDlg PersonDlg(pPerson);
if (PersonDlg.DoModal() == IDOK)
{
// Persons details have been edited, so update row in list box.
m_myListBox.DeleteString(nIndex);
// If sorting the list box, use AddString instead of InsertString.
nIndex = m_myListBox.InsertString(nIndex, pPerson->m_sPersonName);
// Associate row with existing person object.
if (nIndex != LB_ERR && nIndex != LB_ERRSPACE)
{
m_myListBox.SetItemDataPtr(nIndex, pPerson);
}
}
}
}
You will need to delete the pPerson objects in the destructor for the main dialog, e.g., iterate over the rows in the list box using GetItemDataPtr to get the person object for that row, and delete the object.
you project also has files of type .bmp, .ico, .rc2.
i dunnot see these files.
usually these files are in the res directory of your project.
anyway, these files are needed for a "clean" compilation.
do you understand?
anyway, in less words, delete your project's Debug and Release directories, zip everything else and upload here.
Your CPersonDiaglog constructor takes a single parameter of type CWnd*. You need to define a second parameter of type CPerson*. Use it like this:
CPersonDialog PersonDlg(this, pPerson);
i.e., pass the this pointer (pointer to your list box window) as the first parameter.
Your CPersonDiaglog class needs a data member of type CPerson*. In the CPersonDiaglog constructor, assing the passed in pPerson object to this data member. Your CPersonDiaglog class now has access to the data members in the pPerson object.
Watch your spelling - you've used both PersonDlg and PersonDialog in the same function. Be consistent!
Your pPerson class needs data members for each of the attributes of people that you want to record, e.g., person name.
Watch you matching braces - you have one too many. Put the caret cursor before a left brace {, and use the Ctrl+] key combo to find the matching end brace.
Aside from all this, I suggest you get hold of a good book on basic C++ programming, and MFC too. The trial and error method of learning you're currently experiencing is not recommended.
Thanks guys for all your help and advice...
I think that's exactly what i'm going to do (get a book). The thing is i bought Visual C++(Sam's programming C++ in 21 days) and i really felt that i understood most of the stuff i read, and then i bought Jeff Prosise's book Programming windows......and i thought i understood that as well....bought i guess i can't really expect to learn that quickly(6 months).
Thanks for your patience...I think i might sit down and go through all this stuff again.
Regarding the help given above, i have copied it below for creating a list box and populating it (my question is given below after the quotes):
Originally posted by astanley
Well, this is where it gets a (little) bit clever.
Create a class to represent people, e.g., CPerson. The class should have properties for each bit of data about the person, e.g., name, age, height etc. Each person (row) in the list box is an object of this class. Use CListBox::SetItemDataPtr to associate the row in the list box with the person object for that row.
Something like this (CPersonDlg is your popup child dialog):
Code:
OnAdd:
CPersonDlg PersonDlg;
if (PersonDlg.DoModal() == IDOK)
{
// OKed from child dialog, so add new person to list box.
int nIndex = m_myListBox.AddString(PersonDlg.m_sPersonName);
if (nIndex != LB_ERR && nIndex != LB_ERRSPACE)
{
// New person successfully added to list box, so create a person object for them, using
// the member variables from the child dialog.
CPerson* pPerson = new CPerson(PersonDlg.m_sPersonName, PersonDlg.m_nSex, PersonDlg.m_DataOfBirth);
if (pPerson != NULL)
{
// Associate the new person object with the row in the list box.
m_myListBox.SetItemDataPtr(nIndex, pPerson);
}
}
}
OnEdit:
int nIndex = m_myListBox.GetCurSel();
if (nIndex != LB_ERR)
{
// Row is selected in list box, so get person object for this row, and pass to
// contructor for child dialog.
CPerson* pPerson = m_myListBox.GetItemDataPtr(nIndex);
if (pPerson != NULL)
{
CPersonDlg PersonDlg(pPerson);
if (PersonDlg.DoModal() == IDOK)
{
// Persons details have been edited, so update row in list box.
m_myListBox.DeleteString(nIndex);
// If sorting the list box, use AddString instead of InsertString.
nIndex = m_myListBox.InsertString(nIndex, pPerson->m_sPersonName);
// Associate row with existing person object.
if (nIndex != LB_ERR && nIndex != LB_ERRSPACE)
{
m_myListBox.SetItemDataPtr(nIndex, pPerson);
}
}
}
}
You will need to delete the pPerson objects in the destructor for the main dialog, e.g., iterate over the rows in the list box using GetItemDataPtr to get the person object for that row, and delete the object.
I just wanted to find out when learning C++ programming i thought that we could not assign a pointer to something else without deleting it first. But in this example we create a new CPerson on the freestore and then assign its address to the pointer pPerson. And then for the next person we do the same thing again.....My question is, is this dangerous as we are assigning a pointer that's pointer to a certain location in memory to another location without freeing the previous memory!Have i got these wrong???Please help
I just wanted to find out when learning C++ programming i thought that we could not assign a pointer to something else without deleting it first.
No, never assign a pointer to smthng deleted. It would point to garbadge. The pointer should be assigned to smthng existing.
You may assign to another memory location, as long as you are sure you are using the correct pointer type. E.g. a pointer to Person should point to a Person or a subclass of a person...
Free memory when you do not need it. Keep a pointer to dynamically allocated memory so that you can delete it afterwards.
CPerson* pPerson = new CPerson(PersonDlg.m_sPersonName, PersonDlg.m_nSex, PersonDlg.m_DataOfBirth);
is safe because we then store the address the pointer points to into the listbox row for that person:
Code:
m_myListBox.SetItemDataPtr(nIndex, pPerson);
So, we're using the listbox to keep track of all the memory allocations.
Because pPerson is a local varible it will go out of scope once you've call SetItemDataPtr anyway - point a break point after this line and you'll see the value of pPerson becomes garbage. This is perfectly OK, because as I said we've already saved the address into the listbox itself.
Hence my comment before: "You will need to delete the pPerson objects in the destructor for the main dialog, e.g., iterate over the rows in the list box using GetItemDataPtr to get the person object for that row, and delete the object."
That is, once you have finished with the list box, you need to retrieve the addresses from the list box of all of the person objects you created, and delete this memory.
Panayotisk is right - you normally use pointers to hold addresses. But as an address is just a 32 bit value, you can also store them in any 32 bit data type, which is what CListBox::SetItemDataPtr does - from MSDN "Sets the 32-bit value associated with the specified item in a list box to be the specified pointer (void*)."
MASSIVE THANKS!That clears things up but i have another question?
Thanks a lot guys that really clears this things up for me as i find pointers very confusing, another question however is can i then use this pPerson in any function i create within my program to access the information associated in that row:
and secondly when you say delete these pointersin the main dialog i'm assuming this is the same as my view class destructor
and what happens if you don't delete it, should it not delete itself once the view closes i.e the program ends?
* 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.