LVS_EDITLABELS风格的listctrl(nm_customdraw示例)

 帖子


#pragma once
#include "HeaderCtrlEx.h"

class CItemEdit : public CEdit
{
public:
	CItemEdit();
	virtual ~CItemEdit();
	int m_iXPos;

protected:
	afx_msg void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos);
	DECLARE_MESSAGE_MAP()
};

// CMyListCtrl

class CMyListCtrl : public CListCtrl
{
	DECLARE_DYNAMIC(CMyListCtrl)

public:
	CMyListCtrl();
	virtual ~CMyListCtrl();
	void LockHeader(BOOL bLockHeader);

protected:
	virtual void PreSubclassWindow();
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnPaint();
	afx_msg void OnLvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnLvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnKillFocus(CWnd* pNewWnd);
	afx_msg void OnSetFocus(CWnd* pOldWnd);
	DECLARE_MESSAGE_MAP()

private:
	int					m_iSubItem;		//子项标识符
	int					m_iItem;		//主项标识符
	BOOL				m_bHighLight;	//是否高亮文本
	BOOL				m_bFocus;       //是否绘制焦点框
	CItemEdit			m_edtItemEdit;  // 用于子类化EditLabel函数返回的CEdit*指针
	CHeaderCtrlEx		m_HeaderCtrl;
};



// MyListCtrl.cpp : 实现文件
//

#include "stdafx.h"
#include "ListCtrlEx.h"
#include "MyListCtrl.h"


// CMyListCtrl

IMPLEMENT_DYNAMIC(CMyListCtrl, CListCtrl)

CMyListCtrl::CMyListCtrl()
{
	m_iItem = -1;
	m_iSubItem = -1;

	m_bHighLight = FALSE;
	m_bFocus = FALSE;
}

CMyListCtrl::~CMyListCtrl()
{
}


BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
	ON_WM_LBUTTONDOWN()
	ON_WM_PAINT()
	ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, &CMyListCtrl::OnLvnBeginlabeledit)
	ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, &CMyListCtrl::OnLvnEndlabeledit)
	ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CMyListCtrl::OnNMCustomdraw)
	ON_WM_KILLFOCUS()
	ON_WM_SETFOCUS()
END_MESSAGE_MAP()



// CMyListCtrl 消息处理程序

void CMyListCtrl::PreSubclassWindow()
{
	// TODO: 在此添加专用代码和/或调用基类

	CListCtrl::PreSubclassWindow();
	ModifyStyle(0, LVS_EDITLABELS);
	CHeaderCtrl* pHeader = GetHeaderCtrl();
	m_HeaderCtrl.SubclassWindow(pHeader->GetSafeHwnd());
}

void CMyListCtrl::LockHeader(BOOL bLockHeader)
{
	m_HeaderCtrl.LockHeader(bLockHeader);
}

void CMyListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	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 CMyListCtrl::OnPaint()
{
	//	CPaintDC dc(this); // device context for painting
	// TODO: 在此处添加消息处理程序代码
	// 不为绘图消息调用 CListCtrl::OnPaint()
	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 CMyListCtrl::OnLvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
	LV_DISPINFO *pDispInfo = (LV_DISPINFO*)pNMHDR;
	// TODO: 在此添加控件通知处理程序代码
	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 CMyListCtrl::OnLvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
	LV_DISPINFO *pDispInfo = (LV_DISPINFO*)pNMHDR;
	// TODO: 在此添加控件通知处理程序代码
	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;
	}
	//编辑文本时对控件父窗口操作(如单击其它控件)引发"OnEndlabeledit"时刷新控件
	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 CMyListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
	NMLVCUSTOMDRAW* pNMLVCustomDraw = (NMLVCUSTOMDRAW*)pNMHDR;
	// TODO: 在此添加控件通知处理程序代码
	*pResult = CDRF_DODEFAULT;

	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_ITEMPREPAINT | CDDS_SUBITEM) )
	{
		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 == "" )
		{
			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 CMyListCtrl::OnKillFocus(CWnd* pNewWnd)
{
	CListCtrl::OnKillFocus(pNewWnd);

	// TODO: 在此处添加消息处理程序代码
	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 CMyListCtrl::OnSetFocus(CWnd* pOldWnd)
{
	//	CListCtrl::OnSetFocus(pOldWnd);

	// TODO: 在此处添加消息处理程序代码

}


CItemEdit::CItemEdit()
{
}

CItemEdit::~CItemEdit()
{
}


BEGIN_MESSAGE_MAP(CItemEdit, CEdit)
	ON_WM_WINDOWPOSCHANGING()
END_MESSAGE_MAP()


void CItemEdit::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) 
{
	lpwndpos->x = m_iXPos;

	CEdit::OnWindowPosChanging(lpwndpos);
}

源码是  ftd2013 网友写的,下载链接:  http://download.csdn.net/detail/ftd2013/5991065

你可能感兴趣的:(sdk/mfc界面)