CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 17
  1. #1
    Join Date
    Oct 2003
    Location
    Athens
    Posts
    231

    Question multiple input data(ListBox): newbie MFC Programming question?

    Hi Guys,

    Say i have aprogram with my first edit box:

    Edit Box 1asking for Number of People:

    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.

  2. #2
    Join Date
    Apr 2003
    Location
    UK
    Posts
    83
    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.

  3. #3
    Join Date
    Oct 2003
    Location
    Athens
    Posts
    231
    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.

  4. #4
    Join Date
    Apr 2003
    Location
    UK
    Posts
    83
    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.

  5. #5
    Join Date
    Oct 2003
    Location
    Athens
    Posts
    231
    You are an absolute star!!
    Thank you so much astanley…..you can’t imagine how helpful this is...Thanks

  6. #6
    Join Date
    Oct 2003
    Location
    Athens
    Posts
    231

    Program doesn't run!!!

    Hi There,

    I tried the above example in my program just to get the hang of it but its giving errors that i really don't understand...
    Please can anyone help!!!!

    I think the problem is from the class CPerson, because i wasn't sure what to derive it from.....also i haven't deleted any of the objects.

    Please see attached program!
    Attached Files Attached Files

  7. #7
    Join Date
    Feb 2002
    Posts
    3,788

    Re: Program doesn't run!!!

    Originally posted by Ankoump
    Hi There,

    I tried the above example in my program just to get the hang of it but its giving errors that i really don't understand...
    Please can anyone help!!!!

    I think the problem is from the class CPerson, because i wasn't sure what to derive it from.....also i haven't deleted any of the objects.

    Please see attached program!
    post a compilable project.

  8. #8
    Join Date
    Oct 2003
    Location
    Athens
    Posts
    231
    I don't know what you mean...sorry i'm new to this!

    But the program has errors hence that's why i need help..
    Should i just coomment out the points that are causing it and then send it??/

    Please let me know what you suggest!

  9. #9
    Join Date
    Feb 2002
    Posts
    3,788
    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.

  10. #10
    Join Date
    Apr 2003
    Location
    UK
    Posts
    83
    In future please include the res subdirectory in any projects you post.

    When using GetItemDataPtr, you need cast then return value (void*) to your object type, e.g.,

    CPerson* pPerson = static_cast<CPerson*>(m_myListBox.GetItemDataPtr(nIndex));

    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.

  11. #11
    Join Date
    Oct 2003
    Location
    Athens
    Posts
    231
    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.

  12. #12
    Join Date
    Oct 2003
    Location
    Athens
    Posts
    231

    Question Newbie: Visual C++ Programming question?

    Hi guys,

    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

  13. #13
    Join Date
    Apr 2003
    Location
    Athens, Greece
    Posts
    1,094
    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.

    Hope this helps

    Panayotis
    Extreme situations require extreme measures

  14. #14
    Join Date
    Apr 2003
    Location
    UK
    Posts
    83
    The assignment here:

    Code:
    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*)."

  15. #15
    Join Date
    Oct 2003
    Location
    Athens
    Posts
    231

    Question 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:


    nIndex = 0;
    CPerson* pPerson = m_myListBox.GetItemDataPtr(nIndex);
    i.e pPerson->m_strName;


    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?


Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured