可编辑子项ListCtrl控件的完整实现

源码下载: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



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值