Click here to Skip to main content
11,417,390 members (49,288 online)
Click here to Skip to main content

Editing Sub-Items in List Control

, 18 May 2001
Rate this:
Please Sign up or sign in to vote.
Explains how to edit Sub Items in Report style List Control

Introduction

Almost every one of us who are programming in VC++ , will come across the List control. There are many cases where there is a need to represent data in List Control in multiple columns. By default it is not possible to modify the data in the List control itself. In this small article I am putting a simple way to edit any value in any column in a Report style List control. The logic here is simple, whenever user clicks on an sub-item which he wants to modify at that place I am displaying a edit box and allowing to modify the value. Once modified and by clicking the ENTER key, the updated value is set in the List control. Here I am assuming the user is familiar with VC++ and using Class Wizard

Implementation steps:

  1. Using MFC AppWizard, create a Dialog Based application. Give the application name as MultipleColumns. By default the wizard adds OK and Cancel buttons to the Dialog, Remove these two buttons.
  2. Now Add a List-Control and in properties change the style to Report, this style is necessary if we want multiple columns
  3. Add two buttons to the Dialog and name them as OK and Exit
  4. Add one Edit box and in the properties remove the Border style
  5. Using the Class Wizard add the message handlers for the OK and Exit Buttons. Add the following code to those functions
  6. void CMultipleColumnsDlg::OK() 
    {
        CDialog::EndDialog (0); // Add this line
    }
    
    
    void CMultipleColumnsDlg::OnExit() 
    {
        CDialog::EndDialog (0); // Add this line
    }
    
    
  7. Add a function called InsertItems() to the CMulipleColumnsDlg class.
  8. void InsertItems();
    

    In the function handler add the following code

    // This function inserts the default values 
    // into the listControl
    void CMultipleColumnsDlg::InsertItems()
    {
        HWND hWnd = ::GetDlgItem(m_hWnd, IDC_LIST1);
    
        // Set the LVCOLUMN structure with the required 
        // column information
        LVCOLUMN list;
        list.mask =  LVCF_TEXT |LVCF_WIDTH| 
            LVCF_FMT |LVCF_SUBITEM;
        list.fmt = LVCFMT_LEFT;
        list.cx = 50;
        list.pszText   = "S.No";
        list.iSubItem = 0;
        //Inserts the column
        ::SendMessage(hWnd,LVM_INSERTCOLUMN, 
            (WPARAM)0,(WPARAM)&list);
    
        list.cx = 100;
        list.pszText   = "Name";
        list.iSubItem = 1;
        ::SendMessage(hWnd  ,LVM_INSERTCOLUMN, 
            (WPARAM)1,(WPARAM)&list);
    
        list.cx = 100;
        list.pszText   = "Address";
        list.iSubItem = 2;
        ::SendMessage(hWnd  ,LVM_INSERTCOLUMN, 
            (WPARAM)1,(WPARAM)&list);
    
        list.cx = 100;
        list.pszText   = "Country";
        list.iSubItem = 2;
        ::SendMessage(hWnd  ,LVM_INSERTCOLUMN, 
            (WPARAM)1,(WPARAM)&list);
    
        // Inserts first Row with four columns .
        SetCell(hWnd,"1",0,0);
        SetCell(hWnd,"Prabhakar",0,1);
        SetCell(hWnd,"Hyderabad",0,2);
        SetCell(hWnd,"India",0,3);
    
        // Inserts second Row with four columns .
        SetCell(hWnd,"2",1,0);
        SetCell(hWnd,"Uday",1,1); 
        SetCell(hWnd,"Chennai",1,2);
        SetCell(hWnd,"India",1,3);
    
        // Inserts third Row with four columns .
        SetCell(hWnd,"3",2,0);
        SetCell(hWnd,"Saradhi",2,1); 
        SetCell(hWnd,"Bangolore",2,2);
        SetCell(hWnd,"India",2,3);
    
        // Inserts fourth Row with four columns .
        SetCell(hWnd,"4",3,0);
        SetCell(hWnd,"Surya",3,1); 
        SetCell(hWnd,"Calcutta",3,2);
        SetCell(hWnd,"India",3,3);
    }
    
  9. Add another function called SetCell( ) to the CMultipleColumnsDlg class
  10. void SetCell(HWND hWnd1, CString value, int nRow, int nCol);
    

    In the function handler add the following code

    // This function set the text in the specified 
    // SubItem depending on the Row and Column values
    void CMultipleColumnsDlg::SetCell(HWND hWnd1, 
            CString value, int nRow, int nCol)
    {
        TCHAR     szString [256];
        wsprintf(szString,value ,0);
    
        //Fill the LVITEM structure with the 
        //values given as parameters.
        LVITEM lvItem;
        lvItem.mask = LVIF_TEXT;
        lvItem.iItem = nRow;
        lvItem.pszText = szString;
        lvItem.iSubItem = nCol;
        if(nCol >0)
            //set the value of listItem
            ::SendMessage(hWnd1,LVM_SETITEM, 
                (WPARAM)0,(WPARAM)&lvItem);
        else
            //Insert the value into List
            ListView_InsertItem(hWnd1,&lvItem);
    
    }
    
  11. Add one more function called GetItemText() to the same Class
  12. CString GetItemText(HWND hWnd, int nItem, int nSubItem) const;
    

    Inside the function add the following code

    //this function will returns the item 
    //text depending on the item and SubItem Index
    CString CMultipleColumnsDlg::GetItemText(
        HWND hWnd, int nItem, int nSubItem) const
    {
        LVITEM lvi;
        memset(&lvi, 0, sizeof(LVITEM));
        lvi.iSubItem = nSubItem;
        CString str;
        int nLen = 128;
        int nRes;
        do
        {
            nLen *= 2;
            lvi.cchTextMax = nLen;
            lvi.pszText = str.GetBufferSetLength(nLen);
            nRes  = (int)::SendMessage(hWnd, 
                LVM_GETITEMTEXT, (WPARAM)nItem,
                (LPARAM)&lvi);
        } while (nRes == nLen-1);
        str.ReleaseBuffer();
        return str;
    }
    
  13. Also add two member variables to the CMultipleColumnsDlg class which are of type int
  14. int nItem, nSubItem;
    
  15. From the Class wizard add NM_CLICK notification to the List control. Inside the function handler write the following code
  16. //This function Displays an EditBox at the position 
    //where user clicks on a particular SubItem with 
    //Rectangle are equal to the SubItem, thus allows to 
    //modify the value
    void CMultipleColumnsDlg::OnClickList(
            NMHDR* pNMHDR, LRESULT* pResult) 
    {
        Invalidate();
        HWND hWnd1 =  ::GetDlgItem (m_hWnd,IDC_LIST1);
        LPNMITEMACTIVATE temp = (LPNMITEMACTIVATE) pNMHDR;
        RECT rect;
        //get the row number
        nItem = temp->iItem;
        //get the column number
        nSubItem = temp->iSubItem;
        if(nSubItem == 0 || nSubItem == -1 || nItem == -1)
            return ;
        //Retrieve the text of the selected subItem 
        //from the list
        CString str = GetItemText(hWnd1,nItem ,
            nSubItem);
    
        RECT rect1,rect2;
        // this macro is used to retrieve the Rectanle 
        // of the selected SubItem
        ListView_GetSubItemRect(hWnd1,temp->iItem,
            temp->iSubItem,LVIR_BOUNDS,&rect);
        //Get the Rectange of the listControl
        ::GetWindowRect(temp->hdr.hwndFrom,&rect1);
        //Get the Rectange of the Dialog
        ::GetWindowRect(m_hWnd,&rect2);
    
        int x=rect1.left-rect2.left;
        int y=rect1.top-rect2.top;
        
        if(nItem != -1) 
        ::SetWindowPos(::GetDlgItem(m_hWnd,IDC_EDIT1),
            HWND_TOP,rect.left+x,rect.top+4, 
            rect.right-rect.left - 3,
            rect.bottom-rect.top -1,NULL);
        ::ShowWindow(::GetDlgItem(m_hWnd,IDC_EDIT1),SW_SHOW);
        ::SetFocus(::GetDlgItem(m_hWnd,IDC_EDIT1));
        //Draw a Rectangle around the SubItem
        ::Rectangle(::GetDC(temp->hdr.hwndFrom),
            rect.left,rect.top-1,rect.right,rect.bottom);
        //Set the listItem text in the EditBox
        ::SetWindowText(::GetDlgItem(m_hWnd,IDC_EDIT1),str);
        *pResult = 0;
    }
    
    
  17. To handle the ENTER key we need to write the virtual function OnOk in the MultipleColumnsDlg.h, so add the following as protected member
  18. afx_msg void OnOK();
    

    In MultipleColumnsDlg.cpp write the following code.

    // This function handles the ENTER key 
    void CMultipleColumnsDlg::OnOK() 
    {   
        CWnd* pwndCtrl = GetFocus();
        // get the control ID which is 
        // presently having the focus
        int ctrl_ID = pwndCtrl->GetDlgCtrlID();
        CString str;
        switch (ctrl_ID)
        {   //if the control is the EditBox 
            case IDC_EDIT1:
            //get the text from the EditBox
            GetDlgItemText(IDC_EDIT1,str);
    
            //set the value in the listContorl with the
            //specified Item & SubItem values
            SetCell(::GetDlgItem (m_hWnd,IDC_LIST1),
                str,nItem,nSubItem);
    
            ::SendDlgItemMessage(m_hWnd,IDC_EDIT1,
                WM_KILLFOCUS,0,0);
            ::ShowWindow(::GetDlgItem(m_hWnd,IDC_EDIT1),
                SW_HIDE);
                break;     
            default:
                break;
        }
    }
    
    
  19. The last step in the implementation is add the following code in side the OnInitDialog function
  20. 	
    //Set the style to listControl
    ListView_SetExtendedListViewStyle(::GetDlgItem 
            (m_hWnd,IDC_LIST1),LVS_EX_FULLROWSELECT | 
            LVS_EX_GRIDLINES); 
    
    InsertItems();
    ::ShowWindow(::GetDlgItem(m_hWnd,IDC_EDIT1),SW_HIDE);
    

Conclusion

With this I will hope , it will give an idea to edit any sub items in a List control.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

s.prabhakarreddy

United States United States
Presently working in VisualSoft in VC++ and COM

Comments and Discussions

 
QuestionCan't change the first column? Pin
Member 1013141028-Jun-13 9:42
memberMember 1013141028-Jun-13 9:42 
QuestionHow to retrieve data from the columns Pin
PradeepChandra22-Dec-08 2:06
memberPradeepChandra22-Dec-08 2:06 
QuestionHow to prevent editbox visibility on dialog box after changing width of right most column? Pin
login000124-Oct-07 21:05
memberlogin000124-Oct-07 21:05 
Questiondoubts on code int x=rect1.left-rect2.left; How it works? Pin
login000124-Oct-07 20:10
memberlogin000124-Oct-07 20:10 
GeneralModifying without clicking the ENTER key Pin
crisoc24-Jan-06 4:08
membercrisoc24-Jan-06 4:08 
GeneralRe: Modifying without clicking the ENTER key Pin
Vivian De Smedt18-Feb-06 20:13
memberVivian De Smedt18-Feb-06 20:13 
AnswerRe: Modifying without clicking the ENTER key Pin
mones28-Jul-08 1:10
membermones28-Jul-08 1:10 
QuestionAuto forward to next column? Pin
dpsauter30-Dec-04 6:34
memberdpsauter30-Dec-04 6:34 
GeneralFix a bug!!! Pin
SniperLee9-Feb-04 16:32
memberSniperLee9-Feb-04 16:32 
GeneralRe: Fix a bug!!! Pin
ufdya17513-Jun-12 21:48
memberufdya17513-Jun-12 21:48 
GeneralModifying the content automatically Pin
mervick19-Dec-03 6:09
membermervick19-Dec-03 6:09 
GeneralCan't get the row Pin
Rooster24211-Sep-03 11:12
sussRooster24211-Sep-03 11:12 
GeneralRe: Can't get the row Pin
Rooster24211-Sep-03 11:22
sussRooster24211-Sep-03 11:22 
GeneralCEdit placement error Pin
pelloq111-Apr-03 5:01
memberpelloq111-Apr-03 5:01 
GeneralRe: CEdit placement error Pin
Carwarlock16-Jun-03 10:09
memberCarwarlock16-Jun-03 10:09 
GeneralRe: CEdit placement error Pin
Dima Polyakov29-Aug-03 17:01
memberDima Polyakov29-Aug-03 17:01 
GeneralHandling Events Pin
Anonymous24-Oct-02 10:35
sussAnonymous24-Oct-02 10:35 
GeneralRe: Handling Events Pin
quox5-Aug-03 20:12
sussquox5-Aug-03 20:12 
GeneralQuestion... Pin
Puiu24-Sep-02 13:23
sussPuiu24-Sep-02 13:23 
QuestionHow to make the text selected Pin
John Wong13-Sep-02 10:55
memberJohn Wong13-Sep-02 10:55 
AnswerRe: How to make the text selected Pin
Dima Polyakov29-Aug-03 16:58
memberDima Polyakov29-Aug-03 16:58 
GeneralMissing ReleaseDC Pin
Antony Kancidrowski16-Nov-01 0:40
memberAntony Kancidrowski16-Nov-01 0:40 
GeneralRe: Missing ReleaseDC Pin
Jamie.20-Nov-02 7:46
memberJamie.20-Nov-02 7:46 
GeneralIt needs more flexibility Pin
a_dyhrberg12-Sep-01 7:40
membera_dyhrberg12-Sep-01 7:40 
GeneralRe: It needs more flexibility Pin
Anders Dyhrberg12-Sep-01 8:12
memberAnders Dyhrberg12-Sep-01 8:12 
GeneralRe: It needs more flexibility Pin
Dima Polyakov29-Aug-03 16:57
memberDima Polyakov29-Aug-03 16:57 
GeneralFor most flexibility Pin
HoangLan12-Apr-05 1:55
memberHoangLan12-Apr-05 1:55 
GeneralRe: For most flexibility Pin
mones28-Jul-08 1:40
membermones28-Jul-08 1:40 
GeneralDon't use EndDialog(0) Pin
Christian Skovdal Andersen19-May-01 5:00
memberChristian Skovdal Andersen19-May-01 5:00 
GeneralUse PostQuitMessage(0) Pin
HoangLan12-Apr-05 1:43
memberHoangLan12-Apr-05 1:43 
GeneralWhy do it in hard ay Pin
Hesham Desokey19-May-01 3:43
memberHesham Desokey19-May-01 3:43 
GeneralRe: Why do it in hard ay Pin
bennylee22-Jan-02 3:14
memberbennylee22-Jan-02 3:14 
GeneralRe: Why do it in hard ay Pin
Kluch20-Oct-03 13:16
memberKluch20-Oct-03 13:16 
GeneralMore legible! Pin
HoangLan12-Apr-05 1:58
memberHoangLan12-Apr-05 1:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150427.4 | Last Updated 19 May 2001
Article Copyright 2001 by s.prabhakarreddy
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid