一:
国际惯例,直接上代码
二:
.h头文件
// CSkinHeaderCtrl class CSkinHeaderCtrl : public CHeaderCtrl { DECLARE_DYNAMIC(CSkinHeaderCtrl) public: CSkinHeaderCtrl(); virtual ~CSkinHeaderCtrl(); void SetHeaderBk(CString strBkImage); protected: DECLARE_MESSAGE_MAP() afx_msg void OnPaint(); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg LRESULT OnLayout( WPARAM wParam, LPARAM lParam ); virtual void PreSubclassWindow(); void DrawColumn(CDC* pDC, int nIndex); void DrawBackGnd(CDC* pDC); private: Image* m_pBkImage; }; // CSkinListCtrl class CSkinListCtrl : public CListCtrl { DECLARE_DYNAMIC(CSkinListCtrl) public: CSkinListCtrl(); virtual ~CSkinListCtrl(); void SetRowHeight(int nHeight); virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); protected: DECLARE_MESSAGE_MAP() afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); virtual void PreSubclassWindow(); void DrawEveryone(CDC* pDC, int nItem, int nSubItem); private: enum { TEXT_ALIGN_LEFT = 0, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT }; enum { ITEM_UNKNOWN = 0, ITEM_SELECTED, ITEM_FOCUSED, }; int GetTextAlign(int nColumn); int GetItemState(int nItem, int nSubItem); private: CSkinHeaderCtrl m_HeaderCtrl; //列表头控件 int m_nCurSelItem; //当前选中项 int m_nRowHeight; //行高 };
.cpp源文件
// CSkinHeaderCtrl IMPLEMENT_DYNAMIC(CSkinHeaderCtrl, CHeaderCtrl) CSkinHeaderCtrl::CSkinHeaderCtrl(): m_pBkImage(NULL) { SetHeaderBk(_T("..//Skin//ListHeaderBK.png")); } CSkinHeaderCtrl::~CSkinHeaderCtrl() { if(m_pBkImage) { delete m_pBkImage; m_pBkImage = NULL; } } BEGIN_MESSAGE_MAP(CSkinHeaderCtrl, CHeaderCtrl) ON_WM_SIZE() ON_WM_PAINT() ON_MESSAGE(HDM_LAYOUT, OnLayout) END_MESSAGE_MAP() void CSkinHeaderCtrl::SetHeaderBk(CString strBkImage) { ASSERT(m_pBkImage == NULL); m_pBkImage = Image::FromFile(strBkImage); } void CSkinHeaderCtrl::DrawColumn(CDC* pDC, int nIndex) { CRect rect; //获取区域小矩形 GetItemRect(nIndex, &rect); HDITEM hdi; const int c_cchBuffer = 256; TCHAR lpBuffer[c_cchBuffer]; hdi.mask = HDI_TEXT; hdi.pszText = lpBuffer; hdi.cchTextMax = c_cchBuffer; VERIFY(GetItem(nIndex, &hdi)); CString strItemText(lpBuffer); Graphics graph(pDC->m_hDC); RectF rectF(rect.left, rect.top, rect.Width(), rect.Height()); TextureBrush texBrush(m_pBkImage); graph.FillRectangle(&texBrush, rectF); graph.DrawRectangle(&Pen(Color::White), rectF); FontFamily fontFamily(L"微软雅黑"); Gdiplus::Font font(&fontFamily, 10, FontStyleBold, UnitPoint); SolidBrush solidBrush(Color::Black); StringFormat stringFormat; stringFormat.SetLineAlignment(StringAlignmentCenter); stringFormat.SetAlignment(StringAlignmentNear); stringFormat.SetFormatFlags(StringFormatFlagsLineLimit ); //限制一行 rectF.X += 10.0f; //不要完全靠左 不好看 //画文字和按钮 graph.DrawString(strItemText, strItemText.GetLength(), &font, rectF, &stringFormat, &solidBrush); } void CSkinHeaderCtrl::DrawBackGnd(CDC* pDC) { CRect rect; GetClientRect(&rect); Graphics graph(pDC->m_hDC); RectF rectF(rect.left, rect.top, rect.Width(), rect.Height()); TextureBrush texBrush(m_pBkImage); graph.FillRectangle(&texBrush, rectF); } void CSkinHeaderCtrl::OnPaint() { CPaintDC dc(this); CRect rect; GetClientRect(&rect); CMemDCC DCMemory(&dc, &rect); DrawBackGnd(&DCMemory); //计算一共有多少列,绘制每一列 int nCount = GetItemCount(); for(int i= 0; i<nCount; i++) { DrawColumn(&DCMemory, i); } } LRESULT CSkinHeaderCtrl::OnLayout( WPARAM wParam, LPARAM lParam ) { LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam); HD_LAYOUT &hdl = *( HD_LAYOUT * ) lParam; RECT *prc = hdl.prc; WINDOWPOS *pwpos = hdl.pwpos; pwpos->cy = m_pBkImage->GetHeight(); prc->top = m_pBkImage->GetHeight(); return lResult; } void CSkinHeaderCtrl::PreSubclassWindow() { CHeaderCtrl::PreSubclassWindow(); } void CSkinHeaderCtrl::OnSize(UINT nType, int cx, int cy) { CHeaderCtrl::OnSize(nType, cx, cy); Invalidate(); } // CSkinListCtrl IMPLEMENT_DYNAMIC(CSkinListCtrl, CListCtrl) CSkinListCtrl::CSkinListCtrl() { m_nCurSelItem = -1; SetRowHeight(30); } CSkinListCtrl::~CSkinListCtrl() { } BEGIN_MESSAGE_MAP(CSkinListCtrl, CListCtrl) ON_WM_LBUTTONDOWN() ON_WM_CREATE() ON_WM_MEASUREITEM_REFLECT() END_MESSAGE_MAP() // CSkinListCtrl message handlers void CSkinListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); ASSERT(pDC != NULL); int nColumn = m_HeaderCtrl.GetItemCount(); for(int i=0; i<nColumn; i++) { DrawEveryone(pDC, lpDrawItemStruct->itemID, i); } } int CSkinListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CListCtrl::OnCreate(lpCreateStruct) == -1) return -1; CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl(); //用我们自己的headctrl去子类化系统的 if(pHeaderCtrl) { m_HeaderCtrl.SubclassWindow(pHeaderCtrl->m_hWnd); } SetBkColor(RGB(174, 183, 193)); return 1; } void CSkinListCtrl::PreSubclassWindow() { CListCtrl::PreSubclassWindow(); ModifyStyle(NULL, LVS_OWNERDRAWFIXED); CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl(); //用我们自己的headctrl去子类化系统的 if(pHeaderCtrl) { m_HeaderCtrl.SubclassWindow(pHeaderCtrl->m_hWnd); } SetBkColor(RGB(174, 183, 193)); } void CSkinListCtrl::DrawEveryone(CDC* pDC, int nItem, int nSubItem) { CRect rectItem; int nTextAlign; CString strItem; int nItemState; nItemState = GetItemState(nItem, nSubItem); strItem = GetItemText(nItem, nSubItem); nTextAlign = GetTextAlign(nSubItem); VERIFY(GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rectItem)); RectF rectF(rectItem.left, rectItem.top, rectItem.Width(), rectItem.Height()); Graphics graph(pDC->m_hDC); //根据选中状态填充背景 switch(nItemState) { case ITEM_SELECTED: { graph.FillRectangle(&SolidBrush(Color(203, 209, 216)), rectF); break; } default: { graph.FillRectangle(&SolidBrush(Color(174, 183, 193)), rectF); break; } } //根据文本排列方向 画文字 FontFamily fontFamily(L"微软雅黑"); Gdiplus::Font font(&fontFamily, 10, FontStyleRegular, UnitPoint); SolidBrush solidBrush(Color::Black); StringFormat stringFormat; stringFormat.SetLineAlignment(StringAlignmentCenter); switch(nTextAlign) { case TEXT_ALIGN_CENTER: { stringFormat.SetAlignment(StringAlignmentCenter); break; } case TEXT_ALIGN_RIGHT: { stringFormat.SetAlignment(StringAlignmentFar); break; } default: { ASSERT(nTextAlign == TEXT_ALIGN_LEFT); stringFormat.SetAlignment(StringAlignmentNear); rectF.X += 10.0f; //不要完全靠左 不好看 break; } } graph.DrawString(strItem, strItem.GetLength(), &font, rectF, &stringFormat, &solidBrush); } int CSkinListCtrl::GetTextAlign(int nColumn) { LVCOLUMN col; col.mask = LVCF_WIDTH | LVCF_FMT; VERIFY(GetColumn(nColumn, &col)); //获得文字是要居中还是要左右 if(col.fmt & LVCFMT_LEFT) return TEXT_ALIGN_LEFT; else if(col.fmt & LVCFMT_CENTER) return TEXT_ALIGN_CENTER; else if(col.fmt & LVCFMT_RIGHT) return TEXT_ALIGN_RIGHT; //默认左边 return TEXT_ALIGN_LEFT; } int CSkinListCtrl::GetItemState(int nItem, int nSubItem) { if(nItem == m_nCurSelItem) return ITEM_SELECTED; else return ITEM_UNKNOWN; //LVITEM item; //item.mask = LVIF_STATE; //item.iItem = nItem; //item.iSubItem = nSubItem; //VERIFY(GetItem(&item)); //if(item.state & LVIS_SELECTED) // return ITEM_SELECTED; //else if(item.state & LVIS_FOCUSED) // return ITEM_FOCUSED; //else // return ITEM_UNKNOWN; } void CSkinListCtrl::OnLButtonDown(UINT nFlags, CPoint point) { UINT uFlags; int nItem = HitTest(point, &uFlags); if (uFlags & LVHT_ONITEMLABEL) { if(m_nCurSelItem != nItem) { //刷新之前的 CRect rect; GetItemRect(m_nCurSelItem, &rect, LVIR_BOUNDS); InvalidateRect(&rect); //重置 m_nCurSelItem = nItem; } } CListCtrl::OnLButtonDown(nFlags, point); } void CSkinListCtrl::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { if (m_nRowHeight>0) { lpMeasureItemStruct->itemHeight = m_nRowHeight; } } void CSkinListCtrl::SetRowHeight(int nHeight) { m_nRowHeight = nHeight; }