天天看點

CListCtrl 編輯子項

相信很多人用過MFC的新手都知道,MFC雖然封裝了一些常用的控件,但不少控件真正使用起來,與個人的要求可能會有一些差别,總有一些功能不是很友善就能實作的,例如CTabCtrl(Tab控件)的顔色(涉及到自繪、頭大)/CListCtrl的子項編輯。 報表風格的清單控件,在資源裡設定了“可就地編輯”的屬性,子項雖然能夠編輯,但編輯框是出現在第一列的,即不管你選擇修改的項是在第幾列,編輯框總是出現在相應行的第一列位置,很麻煩,而且經過我的嘗試,編輯完後的文本儲存,也是需要自己實作的。

為了簡便實作,我沒有派生子類,而是在資源中添加一個編輯框,通過将編輯框顯示隐藏在指定位置,達到可編輯的目的,在編輯框失去焦點時,将文本顯示在ListCtrl中。

下面是我的實作方法:

  1.  資源裡拖入一個CEdit Box控件,關聯control變量m_SubItemEdit,關聯value變量CString m_strEditText,在對話框初始化函數OnInitDialog()裡将編輯框隐藏起來:           m_SubItemEdit.ShowWindow(SW_HIDE);

2.   在對話框上拖入一個CListCtrl清單控件,設定後屬性,風格(報表-report),添加變量m_ListCtrl,在對話框初始化函數裡加入清單控件的一些初始化操作,

     在 OninitDialog中初始化清單框:

    m_ListCtrl.SetExtendedStyle( //設定風格

                LVS_EX_FLATSB            //扁平風格滾動條

                | LVS_EX_FULLROWSELECT    //允許整行選中

                | LVS_EX_HEADERDRAGDROP   //允許标題拖拽

                | LVS_EX_ONECLICKACTIVATE //高亮顯示

                | LVS_EX_GRIDLINES        //畫出網格線

                );

        m_ListCtrl.InsertColumn(0, _T("姓名"), LVCFMT_LEFT, 150, 0);

        m_ListCtrl.InsertColumn(1, _T("聯系電話"), LVCFMT_LEFT, 150, 1);

        m_ListCtrl.InsertItem(0, _T(""));

        m_ListCtrl.SetItemText(0, 0, _T("周芷若"));

        m_ListCtrl.SetItemText(0, 1, _T("123456789"));

        m_ListCtrl.InsertItem(1, _T(""));

        m_ListCtrl.SetItemText(1, 0, _T("張無忌"));

        m_ListCtrl.SetItemText(1, 1, _T("987654321"));

        m_SubItemEdit.ShowWindow(SW_HIDE);

    3.  響應CListCtrl控件的NM_DBLCLK(訓示使用者在控件内輕按兩下了滑鼠左鍵),以下是響應函數的處理,實作子項的可編輯化。

void CEditListCtrlDlg::OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult)

{

        //LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);

        // TODO:  在此添加控件通知處理程式代碼

        //*pResult = 0;

        NM_LISTVIEW *pNMListCtrl = (NM_LISTVIEW *)pNMHDR;

        if (pNMListCtrl->iItem != -1)

        {

                CRect rect, dlgRect;

                //獲得目前列的寬度以适應如果使用者調整寬度   

                //此處不用獲得的子項rect矩形框來設定寬度   

                //是因第一列時傳回的寬度是整行的寬度,我也不知道為啥   

                int width = m_ListCtrl.GetColumnWidth(pNMListCtrl->iSubItem);

                m_ListCtrl.GetSubItemRect(pNMListCtrl->iItem, pNMListCtrl->iSubItem, LVIR_BOUNDS, rect);

                //是以需要儲存清單的索引   

                //以及子項相對應的行列号索引  

                listSelItem[0] = pNMListCtrl->iItem;

                listSelItem[1] = pNMListCtrl->iSubItem;

                //獲得listctrl矩形框   

                //獲得父對話框的位置以調整CEdit的顯示位置,具體見下面代碼   

                m_ListCtrl.GetWindowRect(&dlgRect);

                ScreenToClient(&dlgRect);

                int height = rect.Height();

                rect.top += (dlgRect.top + 1);

                rect.left += (dlgRect.left + 1);

                rect.bottom = rect.top + height + 2;

                rect.right = rect.left + width + 2;

                m_SubItemEdit.MoveWindow(&rect);

                m_SubItemEdit.ShowWindow(SW_SHOW);

                m_SubItemEdit.SetFocus();

        }

}

4.到了這裡,應該就可以實作輕按兩下編輯控件了,但隻是編輯而已,沒有實作儲存,要實作儲存,還得對CEDIT失去焦點消息進行相應,以下是響應函數,因為我還做了CEdit控件對于Enter鍵實作儲存編輯的功能

void CEditListCtrlDlg::SetListItemText(void)

{

        UpdateData(TRUE);

                //此處的cstrItemTextEdit是CEdit控件的字元串關聯變量   

                m_ListCtrl.SetItemText(listSelItem[0], listSelItem[1], m_strEditText);

                //重置編輯框文本   

                m_SubItemEdit.SetWindowText(_T(""));

                //隐藏編輯框   

                m_SubItemEdit.ShowWindow(SW_HIDE);

        //強制重新整理清單控件(否則視覺上有感覺有點不爽,可以試試^_^)   

           m_ListCtrl.Invalidate();

}

5.   響應CEdit控件的EN_KILLFOCUS函數

void CEditListCtrlDlg::OnEnKillfocusEdit1()

{

        // TODO:  在此添加控件通知處理程式代碼

        SetListItemText();

}

6.處理Enter鍵的響應,是以直接重載對話框的PreTranslateMessage函數,然後在函數裡做處理

BOOL CEditListCtrlDlg::PreTranslateMessage(MSG* pMsg)

{

        // TODO:  在此添加專用代碼和/或調用基類

        if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)

        {

                if (GetFocus()->GetDlgCtrlID() == IDC_EDIT1)

                {

                        //使清單控件獲得焦點,則CEdit會自動失去焦點,觸發EN_KILLFOCUS消息   

                                m_ListCtrl.SetFocus();

                }

                return TRUE;

        }

        return CDialogEx::PreTranslateMessage(pMsg);

}

vc