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