可编辑子项的CListCtrl类

 

大家都知道在MFC中通过给CListCtrl设置LVS_EDITLABELS属性,并且在程序中响应控件的LVN_ENDLABELEDIT消息可以修改列表控件每一行的第一项,也就是主项(Item)。

 

void CEditListCtrlSampleDlg::OnEndlabeleditList1(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
	// TODO: Add your control notification handler code here
	
	*pResult = TRUE;   //TRUE值表示可以修改主项,FALSE值表示不修改主项
}
但是让人郁闷的是,微软留了一手,CListCtrl不支持直接修改子项(SubItem)。下面的代码实现直接修改子项的功能。

 

具体思路如下:

创建一个CEDIT 编辑框,然后把编辑框覆盖当前的 subitem 上,并且使编辑框获取焦点。当编辑框失去焦点时,把编辑框里的文字,显示到 listctrl 控件上,就可以了。为了能够使控件知道何时显示编辑框中的文字,所以还有重写编辑框,当编辑框失去焦点时,通过消息通知 listctrl 控件。 

 

代码如下:
1.新建一个CItemEdit类,该类继承自CEdit
ItemEdit.h文件的代码如下:
class CItemEdit : public CEdit
{
// Construction
public:
	CItemEdit();

// Attributes
public:

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CItemEdit)
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CItemEdit();

	// Generated message map functions
protected:
	//{{AFX_MSG(CItemEdit)
	afx_msg void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos);
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()

public:
	int m_iXPos; 
};
ItemEdit.cpp文件的代码如下:
#include "ItemEdit.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CItemEdit

CItemEdit::CItemEdit()
{
}

CItemEdit::~CItemEdit()
{
}


BEGIN_MESSAGE_MAP(CItemEdit, CEdit)
	//{{AFX_MSG_MAP(CItemEdit)
	ON_WM_WINDOWPOSCHANGING()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CItemEdit message handlers

void CItemEdit::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) 
{
	lpwndpos->x = m_iXPos;
	CEdit::OnWindowPosChanging(lpwndpos);
	
	// TODO: Add your message handler code here
	
}
新建一个CEditListCtrl类,该类继承自CListCtrl,并包含了一个CItemEdit对象的成员变量。
EditListCtrl.h文件的代码如下:
#include "ItemEdit.h" / // CEditListCtrl window class CEditListCtrl : public CListCtrl { // Construction public: CEditListCtrl(); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CEditListCtrl) protected: virtual void PreSubclassWindow(); //}}AFX_VIRTUAL // Implementation public: virtual ~CEditListCtrl(); // Generated message map functions protected: //{{AFX_MSG(CEditListCtrl) afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnBeginlabeledit(NMHDR* pNMHDR, LRESULT* pResult);//开始编辑时的需处理的内容 afx_msg void OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult);//结束编辑时需处理的内容 afx_msg void OnPaint();//控件重绘时需要处理的内容 afx_msg void OnKillFocus(CWnd* pNewWnd);//控件失去焦点需做的处理 //}}AFX_MSG afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult); //自定义控件的绘制 DECLARE_MESSAGE_MAP() private: int m_iItem; int m_iSubItem; BOOL m_bFocus; BOOL m_bHighLight; CItemEdit m_edtItemEdit; };
EditListCtrl.cpp文件的代码如下所示:
#include "EditListCtrl.h"
CEditListCtrl::CEditListCtrl() { m_iItem = -1; m_iSubItem = -1; m_bFocus = FALSE; m_bHighLight = FALSE; } CEditListCtrl::~CEditListCtrl() { } BEGIN_MESSAGE_MAP(CEditListCtrl, CListCtrl) //{{AFX_MSG_MAP(CEditListCtrl) ON_WM_LBUTTONDOWN() ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, OnBeginlabeledit) ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit) ON_WM_PAINT() ON_WM_KILLFOCUS() //}}AFX_MSG_MAP ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) END_MESSAGE_MAP() / // CEditListCtrl message handlers void CEditListCtrl::OnCustomDraw(NMHDR *pNMHDR, LRESULT *pResult) { NMLVCUSTOMDRAW *pNMLVCustomDraw = (NMLVCUSTOMDRAW*) pNMHDR; *pResult = CDRF_DODEFAULT; //NULL if ( pNMLVCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT ) { *pResult = CDRF_NOTIFYITEMDRAW; } else if( pNMLVCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) { *pResult = CDRF_NOTIFYSUBITEMDRAW; } else if ( pNMLVCustomDraw->nmcd.dwDrawStage == (CDDS_SUBITEM | CDDS_ITEMPREPAINT)) { int iItem = (int)pNMLVCustomDraw->nmcd.dwItemSpec; int iSubItem = pNMLVCustomDraw->iSubItem; CDC *pDC = CDC::FromHandle(pNMLVCustomDraw->nmcd.hdc); CString strItemText = GetItemText(iItem, iSubItem); CRect rcItem, rcText; GetSubItemRect(iItem, iSubItem, LVIR_LABEL, rcItem); rcText = rcItem; CSize size = pDC->GetTextExtent(strItemText); if (strItemText == _T("")) { size.cx = 41; } //设置文本高亮矩形 rcText.left += 4; rcText.right = rcText.left + size.cx + 6; if ( rcText.right > rcItem.right ) { rcText.right = rcItem.right; } COLORREF crOldTextColor = pDC->GetTextColor(); if ( m_bFocus ) { if ( (m_iItem == iItem) && (m_iSubItem == iSubItem)) { if ( m_bHighLight ) { pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); pDC->FillSolidRect(&rcText, ::GetSysColor(COLOR_HIGHLIGHT)); } pDC->DrawFocusRect(&rcText); } } rcItem.left += 6; pDC->DrawText(strItemText, &rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOCLIP); pDC->SetTextColor(crOldTextColor); *pResult = CDRF_SKIPDEFAULT; } } void CEditListCtrl::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default m_bFocus = TRUE; LVHITTESTINFO lvhit; lvhit.pt = point; int item = SubItemHitTest(&lvhit); if ( item != -1 && (lvhit.flags & LVHT_ONITEM)) { CListCtrl::OnLButtonDown(nFlags, point); if ( m_bHighLight && m_iItem == lvhit.iItem && m_iSubItem == lvhit.iSubItem ) { //第二次单击 EditLabel(m_iItem); return; } else { //第一次单击 m_iItem = lvhit.iItem; m_iSubItem = lvhit.iSubItem; m_bHighLight = TRUE; } } else { if ( m_edtItemEdit.m_hWnd == NULL) { m_bHighLight = FALSE; } CListCtrl::OnLButtonDown(nFlags, point); } Invalidate(); } void CEditListCtrl::OnBeginlabeledit(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; // TODO: Add your control notification handler code here if ( m_iSubItem >= 0) { ASSERT(m_iItem == pDispInfo->item.iItem); CRect rcSubItem; GetSubItemRect(pDispInfo->item.iItem, m_iSubItem, LVIR_BOUNDS, rcSubItem); HWND hWnd = (HWND) SendMessage(LVM_GETEDITCONTROL); ASSERT( hWnd != NULL); VERIFY(m_edtItemEdit.SubclassWindow(hWnd)); m_edtItemEdit.m_iXPos = rcSubItem.left + 4; m_edtItemEdit.SetWindowText(GetItemText(pDispInfo->item.iItem, m_iSubItem)); } *pResult = 0; } void CEditListCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; // TODO: Add your control notification handler code here LV_ITEM *plvItem = &pDispInfo->item; if ( m_iSubItem >= 0 ) { if ( plvItem->pszText != NULL ) { SetItemText( plvItem->iItem, m_iSubItem, plvItem->pszText); } VERIFY(m_edtItemEdit.UnsubclassWindow() != NULL); *pResult = 0; } CRect rect; GetWindowRect(&rect); CPoint point; ::GetCursorPos(&point); if ( !rect.PtInRect(point)) { m_iItem = -1; m_iSubItem = -1; m_bFocus = FALSE; m_bHighLight = FALSE; } } void CEditListCtrl::OnPaint() { //CPaintDC dc(this); // device context for painting // TODO: Add your message handler code here // Do not call CListCtrl::OnPaint() for painting messages if ( m_iSubItem >= 0 && m_edtItemEdit.m_hWnd ) { CRect rect; CRect rcEdit; m_edtItemEdit.GetWindowRect(rcEdit); ScreenToClient(rcEdit); GetSubItemRect(m_iItem, m_iSubItem, LVIR_LABEL, rect); if ( rcEdit.right < rect.right) { rect.left = rcEdit.right; CClientDC dc(this); dc.FillRect(rect, &CBrush(::GetSysColor(COLOR_WINDOW))); ValidateRect(rect); } } CListCtrl::OnPaint(); } void CEditListCtrl::OnKillFocus(CWnd* pNewWnd) { CListCtrl::OnKillFocus(pNewWnd); // TODO: Add your message handler code here CRect rect; GetWindowRect(&rect); CPoint point; ::GetCursorPos(&point); if ( !rect.PtInRect(point) && GetParent()->GetFocus() != NULL) { m_iItem = -1; m_iSubItem = -1; m_bFocus = FALSE; m_bHighLight = FALSE; Invalidate(); } } void CEditListCtrl::PreSubclassWindow() { // TODO: Add your specialized code here and/or call the base class ModifyStyle(0, LVS_EDITLABELS); CListCtrl::PreSubclassWindow(); }
使用CEditListCtrl类生成的ListCtrl就可以编辑其子项了。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值