List Control控件item的可編輯操作實現


簡介

幾乎每一個使用vc++編程的人,都將會遇到的列表控件。我們會遇到很多需要代表數據在多個欄目的列表控件場合。默認情況下是不可能的修改列表數據。在這個很小的文章我把一個簡單的方法來實現在報告風格的列表控件編輯任意項目的值。這是簡單的邏輯,每當用戶點擊一個他所要修改的子項目,我就在那個地方顯示一個編輯框,允許修改其內容。修改後,並按回車鍵,最新值設置在列表控件。在這裏我假設用戶熟悉vc++和使用類的嚮導

實施步驟:

  1. 使用MFC嚮導,創建一個基於對話框的應用程序。程序命名爲MultipleColumns。應用程序嚮導會默認生成OK和Cancel按鈕,在這裏,我們移除這兩個按鈕。
  2. 添加一個 List-Control控件,將view屬性設置爲Report,這是多列顯示需要的風格。
  3. 添加兩個按鈕,命名爲OK和Cancel。
  4. 添加一個Edit box控件,將Border屬性設置爲False。
  5. 用類嚮導爲OK和Cancel按鈕添加消息處理函數。爲函數添加如下代碼:
    void CMultipleColumnsDlg::OK() 
    {
        CDialog::EndDialog (0); // Add this line
    }
    
    
    void CMultipleColumnsDlg::OnExit() 
    {
        CDialog::EndDialog (0); // Add this line
    }
    
  6. CMulipleColumnsDlg類中添加InsertItems()函數
    void InsertItems();
    

    在函數中添加如下代碼:

    // 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);
    }
  7. CMulipleColumnsDlg類中添加另外一個函數SetCell( )函數
    void SetCell(HWND hWnd1, CString value, int nRow, int nCol);
    

    在函數中添加如下代碼:

    // 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);
    
    }
  8. 再在CMulipleColumnsDlg類中添加函數GetItemText()函數
    CString GetItemText(HWND hWnd, int nItem, int nSubItem) const;
    

    在函數中添加如下代碼:

    //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;
    }
  9. CMultipleColumnsDlg類中添加兩個int型變量
    int nItem, nSubItem;
  10. 從類嚮導中爲 List control控件添加NM_CLICK通知消息。在函數處理中添加如下代碼
  11. //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;
    }
    
    
  12. afx_msg void OnOK();
    

    MultipleColumnsDlg.cpp 中添加如下代碼:

    // 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;
        }
    }
    
  13. 最後一步是在OnInitDialog函數中添加如下代碼
    	
    //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);
    

總結

希望對於在List control控件中可編輯子項目方面,能夠給你一些靈感。

注:

我照着作者步驟完成後,示意圖如下:

原文出處:http://www.codeproject.com/Articles/1124/Editing-Sub-Items-in-List-Control

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章