赞
踩
MFC提供的ListCtrl控件本身是不具备编辑子项功能的。
本文实现可以在ListCtrl中双击项Item出现编辑框和下拉列表框的编辑功能。
如下图所示:
源代码中包含六个以下文件:
1. EditableListCtrl.h
2. EditableListCtrl.cpp
3. ListCtrlEdit.h
4. ListCtrlEdit.cpp
5. ListCtrlCombo.h
6. ListCtrlCombo.cpp
使用时,直接#include “EditableListCtrl.h”即可。
直接贴上源码:
[EditableListCtrl.h]
#pragma once
#include "ListCtrlEdit.h"
#include "ListCtrlCombo.h"
#include <string>
#include <list>
#include <map>
using std::string;
using std::list;
using std::map;
// CEditableListCtrl
enum ColumnCtrlType
{
CCT_NONE = 0,
CCT_COMBOBOX,
CCT_EDITBOX
};
class CEditableListCtrl;
typedef void (*EditableListCtrlItemValueUpdateAftFunc)(
CWnd* pParent,
CEditableListCtrl *pEditableListCtrl,
int iItem, int iSubItem);
class CEditableListCtrl : public CListCtrl
{
DECLARE_DYNAMIC(CEditableListCtrl)
public:
CEditableListCtrl();
virtual ~CEditableListCtrl();
protected:
DECLARE_MESSAGE_MAP()
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);
afx_msg void VScroll(UINT nSBCode, UINT nPos);
afx_msg LRESULT OnEditEnd(WPARAM wParam,LPARAM lParam);
afx_msg LRESULT OnComboEnd(WPARAM wParam,LPARAM lParam);
void ShowEdit(bool bShow, int nItem, int nSubItem, CRect rcCtrl);
void ShowCombo(bool bShow, int nItem, int nSubItem, CRect rcCtrl);
public:
// 设置列控件的类型
void SetColumnCtrlType(int nColumn, ColumnCtrlType ctrlType);
// 设置列控件Combox的值
void SetColumnComboValue(int nColumn, list<string>& lstValue);
// 设置项更新后回调函数
void SetItemUpdateAftCallBackFunc(EditableListCtrlItemValueUpdateAftFunc func);
private:
CListCtrlEdit m_edit;
CListCtrlCombo m_combo;
int nItem; // 当前点击项
int nSubItem; // 当前点击子项
bool m_bEditVisible; // Edit是否可见
bool m_bComboVisible; // ComboBox是否可见
map<int, ColumnCtrlType> m_Col2CtrlType;
map<int, list<string> > m_Col2ComboValue;
EditableListCtrlItemValueUpdateAftFunc m_ItemValueUpdateAftFunc;
};
[EditableListCtrl.cpp]
// EditableListCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "EditableListCtrl.h"
// CEditableListCtrl
IMPLEMENT_DYNAMIC(CEditableListCtrl, CListCtrl)
CEditableListCtrl::CEditableListCtrl()
: m_bEditVisible(false), m_bComboVisible(false), nItem(-1), nSubItem(-1), m_ItemValueUpdateAftFunc(NULL)
{
}
CEditableListCtrl::~CEditableListCtrl()
{
}
void CEditableListCtrl::SetColumnCtrlType(int nColumn, ColumnCtrlType ctrlType)
{
m_Col2CtrlType[nColumn] = ctrlType;
}
void CEditableListCtrl::SetColumnComboValue(int nColumn, list<string>& lstValue)
{
m_Col2ComboValue[nColumn].clear();
list<string>::iterator iterValue = lstValue.begin();
for (; iterValue != lstValue.end(); ++iterValue)
{
m_Col2ComboValue[nColumn].push_back(*iterValue);
}
}
void CEditableListCtrl::SetItemUpdateAftCallBackFunc(EditableListCtrlItemValueUpdateAftFunc func)
{
m_ItemValueUpdateAftFunc = func;
}
void CEditableListCtrl::ShowEdit(bool bShow, int nItem, int nSubItem, CRect rcCtrl)
{
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);
m_bEditVisible = false;
m_edit.SetFont(this->GetFont());
}
if (bShow == TRUE)
{
CString cstrItem = GetItemText(nItem, nSubItem);
m_edit.MoveWindow(&rcCtrl);
m_edit.ShowWindow(SW_SHOW);
m_bEditVisible = true;
m_edit.SetWindowText(cstrItem);
m_edit.SetFocus();
m_edit.SetSel(-1);
}
else
{
m_edit.ShowWindow(SW_HIDE);
m_bEditVisible = false;
}
}
void CEditableListCtrl::ShowCombo(bool bShow, int nItem, int nSubItem, CRect rcCtrl)
{
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);
m_bComboVisible = false;
m_combo.SetFont(this->GetFont());
}
if (bShow == TRUE && !m_Col2ComboValue[nSubItem].empty())
{
CString cstrItem = GetItemText(nItem, nSubItem);
rcCtrl.bottom += 100;
m_combo.MoveWindow(&rcCtrl);
m_combo.ShowWindow(SW_SHOW);
m_bComboVisible = true;
m_combo.SetWindowText(cstrItem);
m_combo.SetFocus();
m_combo.ResetContent();
list<string>::iterator iterValue = m_Col2ComboValue[nSubItem].begin();
for (; iterValue != m_Col2ComboValue[nSubItem].end(); ++iterValue)
{
m_combo.AddString(iterValue->c_str());
}
m_combo.SetCurSel(-1);
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);
m_bComboVisible = false;
}
}
BEGIN_MESSAGE_MAP(CEditableListCtrl, CListCtrl)
ON_WM_LBUTTONDBLCLK()
ON_NOTIFY(HDN_BEGINTRACKA, 0, &CEditableListCtrl::OnHdnBegintrack)
ON_NOTIFY(HDN_BEGINTRACKW, 0, &CEditableListCtrl::OnHdnBegintrack)
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_MESSAGE(WM_USER_EDIT_END, OnEditEnd)
ON_MESSAGE(WM_USER_COMBO_END, OnComboEnd)
END_MESSAGE_MAP()
// CEditableListCtrl message handlers
LRESULT CEditableListCtrl::OnEditEnd(WPARAM wParam, LPARAM lParam)
{
CString strText;
m_edit.GetWindowText(strText);
SetItemText(nItem,nSubItem,strText);
if (m_ItemValueUpdateAftFunc != NULL)
{
(*m_ItemValueUpdateAftFunc)(this->GetParent(), this, nItem, nSubItem);
}
ShowEdit(false, -1, -1, CRect());
return 0;
}
LRESULT CEditableListCtrl::OnComboEnd(WPARAM wParam, LPARAM lParam)
{
int nSel = m_combo.GetCurSel();
if (nSel != -1)
{
CString cstrTextSel;
m_combo.GetLBText(nSel, cstrTextSel);
SetItemText(nItem, nSubItem, cstrTextSel);
if (m_ItemValueUpdateAftFunc != NULL)
{
(*m_ItemValueUpdateAftFunc)(this->GetParent(), this, nItem, nSubItem);
}
}
ShowCombo(false, -1, -1, CRect());
return 0;
}
void CEditableListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
LVHITTESTINFO lvhti;
lvhti.pt = point;
nItem = SubItemHitTest(&lvhti);
if (nItem == -1)
{
return;
}
nSubItem = lvhti.iSubItem;
ColumnCtrlType colCtrlType = CCT_NONE;
if (m_Col2CtrlType.find(nSubItem) == m_Col2CtrlType.end())
{
return;
}
else
{
colCtrlType = m_Col2CtrlType[nSubItem];
}
CRect rcCtrl;
GetSubItemRect(nItem, nSubItem, LVIR_LABEL, rcCtrl);
switch (colCtrlType)
{
case CCT_NONE:
break;
case CCT_EDITBOX:
ShowEdit(TRUE, nItem, nSubItem, rcCtrl);
break;
case CCT_COMBOBOX:
ShowCombo(TRUE, nItem, nSubItem, rcCtrl);
break;
default:
break;
}
CListCtrl::OnLButtonDblClk(nFlags, point);
}
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;
}
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);
}
[ListCtrlEdit.h]
#pragma once
#define WM_USER_EDIT_END WM_USER+101
// CListCtrlEdit
class CListCtrlEdit : public CEdit
{
DECLARE_DYNAMIC(CListCtrlEdit)
public:
CListCtrlEdit();
virtual ~CListCtrlEdit();
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
};
[ListCtrlEdit.cpp]
// ListCtrlEdit.cpp : implementation file
//
#include "stdafx.h"
#include "ListCtrlEdit.h"
// CListCtrlEdit
IMPLEMENT_DYNAMIC(CListCtrlEdit, CEdit)
CListCtrlEdit::CListCtrlEdit()
{
}
CListCtrlEdit::~CListCtrlEdit()
{
}
BEGIN_MESSAGE_MAP(CListCtrlEdit, CEdit)
ON_WM_KILLFOCUS()
ON_WM_MOUSEWHEEL()
END_MESSAGE_MAP()
// CListCtrlEdit message handlers
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);
}
BOOL CListCtrlEdit::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
CWnd *pParent = this->GetParent();
::PostMessage(pParent->GetSafeHwnd(), WM_USER_EDIT_END, 0, 0);
return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}
[ListCtrlCombo.h]
#pragma once
#define WM_USER_COMBO_END WM_USER+102
// CListCtrlCombo
class CListCtrlCombo : public CComboBox
{
DECLARE_DYNAMIC(CListCtrlCombo)
public:
CListCtrlCombo();
virtual ~CListCtrlCombo();
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnKillFocus(CWnd* pNewWnd);
};
[ListCtrlCombo.cpp]
// ListCtrlCombo.cpp : implementation file
//
#include "stdafx.h"
#include "ListCtrlCombo.h"
// CListCtrlCombo
IMPLEMENT_DYNAMIC(CListCtrlCombo, CComboBox)
CListCtrlCombo::CListCtrlCombo()
{
}
CListCtrlCombo::~CListCtrlCombo()
{
}
BEGIN_MESSAGE_MAP(CListCtrlCombo, CComboBox)
ON_WM_KILLFOCUS()
END_MESSAGE_MAP()
// CListCtrlCombo message handlers
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);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。