247 lines
6.0 KiB
C++
247 lines
6.0 KiB
C++
#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<NMLVCUSTOMDRAW *>(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<int> (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<LPNMITEMACTIVATE>(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();
|
|
} |