#include "StdAfx.h" #include "CXLSListCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif CXLSListCtrl::CXLSListCtrl() { m_nCurItem = -1; m_nCurSubItem = -1; m_nPadding = 5; m_crHightLightOut = RGB(0, 0, 0); m_crHighLight = RGB(0,255,255); m_crGreen = RGB(0, 255, 0); m_crRed = RGB(255, 0, 0); m_crWindow = ::GetSysColor(COLOR_WINDOW); m_crWindowText = ::GetSysColor(COLOR_WINDOWTEXT); } CXLSListCtrl::~CXLSListCtrl() { } BEGIN_MESSAGE_MAP(CXLSListCtrl, CListCtrl) //{{AFX_MSG_MAP(CXLSListCtrl) ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CXLSListCtrl::OnNMCustomdraw) ON_NOTIFY_REFLECT_EX(NM_CLICK, &CXLSListCtrl::OnNMClick) ON_WM_ERASEBKGND() ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() void CXLSListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult) { NMLVCUSTOMDRAW *pLVCD = reinterpret_cast(pNMHDR); // Take the default processing unless we set this to something else below. *pResult = CDRF_DODEFAULT; // First thing - check the draw stage. If it's the control's prepaint // stage, then tell Windows we want messages for every item. if (pLVCD->nmcd.dwDrawStage == CDDS_PREPAINT) { *pResult = CDRF_NOTIFYITEMDRAW; } else if (pLVCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) { // This is the notification message for an item. We'll request // notifications before each subitem's prepaint stage. *pResult = CDRF_NOTIFYSUBITEMDRAW; } else if (pLVCD->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM)) { // This is the prepaint stage for a subitem. Here's where we set the // item's text and background colors. Our return value will tell // Windows to draw the subitem itself, but it will use the new colors // we set here. int nItem = static_cast (pLVCD->nmcd.dwItemSpec); int nSubItem = pLVCD->iSubItem; EquHolder *pHolder = (EquHolder *)GetItemData(nItem); COLORREF crText = m_crWindowText; COLORREF crBkgnd = m_crWindow; if (pHolder) { crBkgnd = m_crGreen;//绿色 } // store the colors back in the NMLVCUSTOMDRAW struct pLVCD->clrText = crText; pLVCD->clrTextBk = crBkgnd; CDC *pDC = CDC::FromHandle(pLVCD->nmcd.hdc); CRect rect; GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect); DrawText(nItem, nSubItem, pDC, crText, crBkgnd, rect, pHolder); *pResult = CDRF_SKIPDEFAULT; // We've painted everything. } } void CXLSListCtrl::DrawText(int nItem,int nSubItem,CDC *pDC, COLORREF crText,COLORREF crBkgnd, CRect &rect, EquHolder *pHolder) { ASSERT(pDC); if (rect.IsRectEmpty()) { return; } if (pHolder != NULL) { if (pHolder->nFrCol == nSubItem) { if (_tcslen(pHolder->szFrEqu) > 0) crBkgnd = m_crGreen;//绿色 else crBkgnd = m_crRed; pDC->FillSolidRect(&rect, crBkgnd); } else if (pHolder->nToCol == nSubItem) { if (_tcslen(pHolder->szToEqu) > 0) crBkgnd = m_crGreen;//绿色 else crBkgnd = m_crRed; pDC->FillSolidRect(&rect, crBkgnd); } else { crBkgnd = m_crWindow; } } //绘制外框 if (m_nCurItem == nItem && m_nCurSubItem == nSubItem) { //黑色-靛蓝-黑色 三个矩形框 CRect rcHit = rect; pDC->Draw3dRect(rcHit, m_crHightLightOut, m_crHightLightOut); rcHit.DeflateRect(1,1); pDC->Draw3dRect(rcHit, m_crHighLight, m_crHighLight); rcHit.DeflateRect(1, 1); pDC->Draw3dRect(rcHit, m_crHightLightOut, m_crHightLightOut); } CString str; str = GetItemText(nItem, nSubItem); if (!str.IsEmpty()) { UINT nFormat = DT_VCENTER | DT_SINGLELINE | DT_LEFT; CFont *pOldFont = NULL; CFont boldfont; // check if bold specified for subitem if (pHolder != NULL) { CFont *font = pDC->GetCurrentFont(); if (font) { LOGFONT lf; font->GetLogFont(&lf); lf.lfWeight = FW_BOLD; boldfont.CreateFontIndirect(&lf); pOldFont = pDC->SelectObject(&boldfont); } } pDC->SetBkMode(TRANSPARENT); pDC->SetTextColor(crText); pDC->SetBkColor(crBkgnd); rect.DeflateRect(m_nPadding, 0); pDC->DrawText(str, &rect, nFormat); rect.InflateRect(m_nPadding, 0); if (pOldFont) pDC->SelectObject(pOldFont); } } BOOL CXLSListCtrl::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast(pNMHDR); CRect rcLast,rcThis; GetItemRect(m_nCurItem, rcLast, LVIR_BOUNDS); InvalidateRect(rcLast); m_nCurItem = pNMItemActivate->iItem; m_nCurSubItem = pNMItemActivate->iSubItem; GetItemRect(m_nCurItem, rcThis, LVIR_BOUNDS); InvalidateRect(rcThis); RedrawWindow(rcLast); RedrawWindow(rcThis); *pResult = 0; return FALSE; // return FALSE to send message to parent also - // NOTE: MSDN documentation is incorrect } BOOL CXLSListCtrl::OnEraseBkgnd(CDC *pDC) { return CListCtrl::OnEraseBkgnd(pDC); /*CRect rectClip, rectTop, rectBottom, rectRight; int nItemCount = GetItemCount(); if (!nItemCount) // Empty XListCtrl, nothing to do, CListCtrl will return CListCtrl::OnEraseBkgnd(pDC); // erase the Background if (pDC->GetClipBox(&rectClip) == ERROR) { ASSERT(false); return CListCtrl::OnEraseBkgnd(pDC); } int nFirstRow = GetTopIndex(); int nLastRow = nFirstRow + GetCountPerPage(); nLastRow = min(nLastRow, nItemCount - 1); // Last Item displayed in Ctrl CListCtrl::GetSubItemRect(nFirstRow, 0, LVIR_BOUNDS, rectTop); CListCtrl::GetSubItemRect(nLastRow, 0, LVIR_BOUNDS, rectBottom); CRect rectEraseTop = rectClip; rectEraseTop.bottom = rectTop.top; pDC->FillSolidRect(rectEraseTop, m_crWindow); CRect rectEraseBottom = rectClip; rectEraseBottom.top = rectBottom.bottom; pDC->FillSolidRect(rectEraseBottom, m_crWindow); CRect rectEraseRight = rectClip; rectEraseRight.top = rectTop.top; rectEraseRight.bottom = rectBottom.bottom; rectEraseRight.left = rectTop.right; pDC->FillSolidRect(rectEraseRight, m_crWindow); return TRUE;*/ } void CXLSListCtrl::OnDestroy() { int n = GetItemCount(); for (int i = 0; i < n; i++) { EquHolder *pHolder = (EquHolder *)GetItemData(i); if (pHolder != NULL) delete pHolder; CListCtrl::SetItemData(i, 0); } CListCtrl::OnDestroy(); }