源码下载: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 default CRect 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 here if (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 default if (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 default if (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; } } } else m_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 here CWnd *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 here CWnd *pParent = this->GetParent(); ::PostMessage(pParent->GetSafeHwnd(), WM_USER_COMBO_END, 0, 0); }效果如下
参考文章:
http://blog.csdn.net/lixiaomin_235/article/details/4096885