源碼下載:http://download.csdn.net/detail/wangyao1052/4604942
MFC提供的ListCtrl控制項本身是不具備編輯子項功能的,我們現在建立一個可編輯子項的ListCtrl控制項用於記錄人員的名字、年齡、性別。其中,雙擊年齡項會出現EditBox讓使用者編輯修改年齡,雙擊性別項會出現ComboBox讓使用者選擇性別。
實現如下:
我們需要實現3個類:CEditableListCtrl繼承自CListCtrl,CListCtrlEdit繼承自CEdit,CListCtrlCombo繼承自CComboBox。CListCtrlEdit和CListCtrlCombo是CEditableListCtrl要用到的EditBox和ComboBox控制項的類,這兩個類非常簡單,就是在失去焦點時向父視窗CEditableListCtrl發送訊息通知。
一、CEditableListCtrl
注意新增部分
class CEditableListCtrl : public CListCtrl{DECLARE_DYNAMIC(CEditableListCtrl)public:CEditableListCtrl();virtual ~CEditableListCtrl();protected:DECLARE_MESSAGE_MAP()//-----------------新增部分----------------------public:afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);afx_msg void OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult);afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);public:void ShowEdit(bool bShow, int nItem, int nSubItem, CRect rcCtrl);void ShowCombo(bool bShow, int nItem, int nSubItem, CRect rcCtrl);afx_msg LRESULT OnEditEnd(WPARAM wParam,LPARAM lParam);afx_msg LRESULT OnComboEnd(WPARAM wParam,LPARAM lParam);private:CListCtrlEdit m_edit;CListCtrlCombo m_combo;int nItem; // 當前點擊項int nSubItem; // 當前點擊子項bool m_bEditVisible; // Edit是否可見bool m_bComboVisible; // ComboBox是否可見};
1、滑鼠雙擊訊息WM_LBUTTONDBLCLK
如果雙擊的是年齡項就顯示EditBox供使用者編輯修改,如果雙擊的是性別項就顯示ComboBox供使用者選擇修改。
void CEditableListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point){// TODO: Add your message handler code here and/or call defaultCRect rcCtrl;LVHITTESTINFO lvhti;lvhti.pt = point;nItem = SubItemHitTest(&lvhti);if (nItem == -1) return;nSubItem = lvhti.iSubItem;GetSubItemRect(nItem, nSubItem, LVIR_LABEL, rcCtrl);if (lvhti.iSubItem == 1)ShowEdit(TRUE, nItem, nSubItem, rcCtrl);else if (lvhti.iSubItem == 2)ShowCombo(TRUE, nItem, nSubItem, rcCtrl);CListCtrl::OnLButtonDblClk(nFlags, point);}
2、開始拖動表頭訊息HDN_BEGINTRACKA
響應EditBox和ComboBox失去焦點的事件
void CEditableListCtrl::OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult){LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);// TODO: Add your control notification handler code hereif (m_edit.m_hWnd != NULL && m_bEditVisible)OnEditEnd(0, 0);if (m_combo.m_hWnd != NULL && m_bComboVisible)OnComboEnd(0, 0);*pResult = 0;}
3、水平與垂直捲軸拖動事件
響應EditBox和ComboBox失去焦點的事件
void CEditableListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar){// TODO: Add your message handler code here and/or call defaultif (m_edit.m_hWnd != NULL && m_bEditVisible)OnEditEnd(0, 0);if (m_combo.m_hWnd != NULL && m_bComboVisible)OnComboEnd(0, 0);CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);}void CEditableListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar){// TODO: Add your message handler code here and/or call defaultif (m_edit.m_hWnd != NULL && m_bEditVisible)OnEditEnd(0, 0);if (m_combo.m_hWnd != NULL && m_bComboVisible)OnComboEnd(0, 0);CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);}
4、ComboBox與EditBox失去焦點響應
CListCtrlEdit類和CListCtrlCombo類中,在失去焦點時會向父視窗發送自訂訊息,以下訊息處理函數就是用於處理這兩個訊息。
#define WM_USER_EDIT_END WM_USER+101
#define WM_USER_COMBO_END WM_USER+102
ON_MESSAGE(WM_USER_EDIT_END, OnEditEnd)
ON_MESSAGE(WM_USER_COMBO_END, OnComboEnd)
LRESULT CEditableListCtrl::OnEditEnd(WPARAM wParam, LPARAM lParam){ CString strText; m_edit.GetWindowText(strText); SetItemText(nItem,nSubItem,strText); ShowEdit(false, -1, -1, CRect()); return 0;}LRESULT CEditableListCtrl::OnComboEnd(WPARAM wParam, LPARAM lParam){ int nSel = m_combo.GetCurSel(); CString cstrTextSel; m_combo.GetLBText(nSel, cstrTextSel); SetItemText(nItem, nSubItem, cstrTextSel); ShowCombo(false, -1, -1, CRect()); return 0;}
5、ShowEdit與ShowCombo
void CEditableListCtrl::ShowEdit(bool bShow, int nItem, int nSubItem, CRect rcCtrl){ m_bEditVisible = bShow; if (m_edit.m_hWnd == NULL) { m_edit.Create(ES_AUTOHSCROLL | WS_CHILD | ES_LEFT | ES_WANTRETURN | WS_BORDER,CRect(0,0,0,0), this, 1001); m_edit.ShowWindow(SW_HIDE); CFont tpFont; tpFont.CreateStockObject(DEFAULT_GUI_FONT); m_edit.SetFont(&tpFont); tpFont.DeleteObject(); } if (bShow == TRUE) { CString cstrItem = GetItemText(nItem, nSubItem); m_edit.MoveWindow(&rcCtrl); m_edit.ShowWindow(SW_SHOW); m_edit.SetWindowText(cstrItem); m_edit.SetFocus(); m_edit.SetSel(-1); } else m_edit.ShowWindow(SW_HIDE);}void CEditableListCtrl::ShowCombo(bool bShow, int nItem, int nSubItem, CRect rcCtrl){m_bComboVisible = bShow;if (m_combo.m_hWnd == NULL){m_combo.Create(ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_CHILD | ES_LEFT | CBS_DROPDOWNLIST,CRect(0,0,0,0), this, 1002);m_combo.ShowWindow(SW_HIDE);CFont tpFont;tpFont.CreateStockObject(DEFAULT_GUI_FONT);m_combo.SetFont(&tpFont);tpFont.DeleteObject();m_combo.AddString(TEXT("Male"));m_combo.AddString(TEXT("Female"));}if (bShow == TRUE){m_combo.SetCurSel(-1);CString cstrItem = GetItemText(nItem, nSubItem);m_combo.MoveWindow(&rcCtrl);m_combo.ShowWindow(SW_SHOW);m_combo.SetWindowText(cstrItem);m_combo.SetFocus();int nItems = m_combo.GetCount();for (int i=0; i<nItems; ++i){CString cstrItemText;m_combo.GetLBText(i, cstrItemText);if (cstrItem == cstrItemText){m_combo.SetCurSel(i);break;}}}elsem_combo.ShowWindow(SW_HIDE);}
二、CListCtrlEdit
class CListCtrlEdit : public CEdit{DECLARE_DYNAMIC(CListCtrlEdit)public:CListCtrlEdit();virtual ~CListCtrlEdit();protected:DECLARE_MESSAGE_MAP()public:afx_msg void OnKillFocus(CWnd* pNewWnd);};
失去焦時間點事件
void CListCtrlEdit::OnKillFocus(CWnd* pNewWnd){CEdit::OnKillFocus(pNewWnd);// TODO: Add your message handler code hereCWnd *pParent = this->GetParent();::PostMessage(pParent->GetSafeHwnd(), WM_USER_EDIT_END, 0, 0);}
三、CListCtrlCombo
class CListCtrlCombo : public CComboBox{DECLARE_DYNAMIC(CListCtrlCombo)public:CListCtrlCombo();virtual ~CListCtrlCombo();protected:DECLARE_MESSAGE_MAP()public:afx_msg void OnKillFocus(CWnd* pNewWnd);};
失去焦時間點事件
void CListCtrlCombo::OnKillFocus(CWnd* pNewWnd){CComboBox::OnKillFocus(pNewWnd);// TODO: Add your message handler code hereCWnd *pParent = this->GetParent();::PostMessage(pParent->GetSafeHwnd(), WM_USER_COMBO_END, 0, 0);}
效果如下
參考文章:
http://blog.csdn.net/lixiaomin_235/article/details/4096885