帖子
#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);
}