#include "stdafx.h" #include "ApredTreeCtrl2.h" #define ROFFSET 7 #define WIDE 10 #define WIDE2 5 #define EXPANDED_WIDE 8 #define BADGE_HIDE 0 #define BADGE_DOT 1 #define BADGE_NUMBER 2 #define BADGE_DOT_WIDTH 12 #define BADGE_NUMBER_WIDTH 20 IMPLEMENT_DYNAMIC(CApredTreeCtrl2, CTreeCtrl) CApredTreeCtrl2::CApredTreeCtrl2() { m_hBrushItem[0] = NULL; m_hBrushItem[1] = NULL; m_hBrushItem[2] = NULL; m_crItemBk[0] = GetSysColor(COLOR_WINDOW); m_crItemBk[1] = GetSysColor(COLOR_HIGHLIGHT); m_crItemBk[2] = RGB(204, 206, 219); m_crItemBtn[0] = RGB(30, 30, 30); m_crItemBtn[1] = RGB(255, 255, 255); m_crItemBtn[2] = RGB(255, 255, 255); } CApredTreeCtrl2::~CApredTreeCtrl2() { if (m_hBrushItem[0] != NULL) { ::DeleteObject(m_hBrushItem[0]); } if (m_hBrushItem[1] != NULL) { ::DeleteObject(m_hBrushItem[1]); } if (m_hBrushItem[2] != NULL) { ::DeleteObject(m_hBrushItem[2]); } } BEGIN_MESSAGE_MAP(CApredTreeCtrl2, CTreeCtrl) ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CApredTreeCtrl2::OnNMCustomdraw) END_MESSAGE_MAP() void CApredTreeCtrl2::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult) { LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); LPNMTVCUSTOMDRAW lpnmcd = (LPNMTVCUSTOMDRAW)pNMCD; HTREEITEM hItem; UINT unt; *pResult = 0; switch (lpnmcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: *pResult = CDRF_NOTIFYITEMDRAW; m_items.clear(); break; case CDDS_ITEMPREPAINT: m_items[(HTREEITEM)lpnmcd->nmcd.dwItemSpec] = lpnmcd->iLevel; hItem = (HTREEITEM)lpnmcd->nmcd.dwItemSpec; if (hItem != NULL) { if ( (GetItemState(hItem, TVIS_SELECTED) & TVIS_SELECTED)== TVIS_SELECTED) { if (GetFocus() != this) { lpnmcd->clrTextBk = RGB(204, 206, 219); } } } *pResult = CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT; // ¶©ÔÄ»æÖƽáÊøÍ¨Öª break; case CDDS_ITEMPOSTPAINT: // Ïî»æÖÆ½áÊøÍ¨Öª unt = GetIndent(); hItem = (HTREEITEM)lpnmcd->nmcd.dwItemSpec; auto iter = m_items.find(hItem); if (iter != m_items.end()) { CRect button_rect = pNMCD->rc; button_rect.right = button_rect.left + unt + 5; int off = unt * iter->second; button_rect.OffsetRect(off, 0); DrawItemButton(hItem, pNMCD->hdc, &button_rect); // ÊÇ·ñÓÐСԲµã CRect rcItem = pNMCD->rc; Gdiplus::Graphics graphics(pNMCD->hdc); graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); if (m_badges.find(hItem) != m_badges.end()) { BADGE& badge = m_badges[hItem]; if (badge.type == BADGE_DOT) { Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(badge.badgeBackground), GetGValue(badge.badgeBackground), GetBValue(badge.badgeBackground))); int x = rcItem.right - 18 - BADGE_DOT_WIDTH; int y = rcItem.top + (rcItem.Height() - BADGE_DOT_WIDTH) / 2; graphics.FillEllipse(&brush, x, y, BADGE_DOT_WIDTH, BADGE_DOT_WIDTH); } else if (badge.type == BADGE_NUMBER) { Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(badge.badgeBackground), GetGValue(badge.badgeBackground), GetBValue(badge.badgeBackground))); int x = rcItem.right - 18 - BADGE_NUMBER_WIDTH; int y = rcItem.top + (rcItem.Height() - BADGE_NUMBER_WIDTH) / 2; graphics.FillEllipse(&brush, x, y, BADGE_NUMBER_WIDTH, BADGE_NUMBER_WIDTH); RECT rcBadge; rcBadge.left = x; rcBadge.right = rcBadge.left + BADGE_NUMBER_WIDTH; rcBadge.top = y; rcBadge.bottom = rcBadge.top + BADGE_NUMBER_WIDTH; ::SetTextColor(pNMCD->hdc, badge.badgeForeground); char szBuffer[32]; sprintf_s(szBuffer, 32, "%d%s", min(badge.number, 9), badge.number > 9 ? "+" : ""); DrawText(pNMCD->hdc, szBuffer, (int)strlen(szBuffer), &rcBadge, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } } *pResult = CDRF_SKIPDEFAULT; } break; } } void CApredTreeCtrl2::DrawItemButton(HTREEITEM hItem, HDC hDC, CRect* pRect) { if (!ItemHasChildren(hItem)) { return; } // °´Å¥ÒªË¢Ò»Ï ::FillRect(hDC, pRect, GetItemBkBrush(hItem)); if ((GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED) == TVIS_EXPANDED) { int nBottomOffset = (pRect->Height() - EXPANDED_WIDE) / 2; POINT pt[3]; pt[0].x = pRect->right - ROFFSET - EXPANDED_WIDE; pt[0].y = pRect->bottom - nBottomOffset; pt[1].x = pRect->right - ROFFSET; pt[1].y = pRect->bottom - nBottomOffset; pt[2].x = pRect->right - ROFFSET; pt[2].y = pRect->bottom - nBottomOffset - EXPANDED_WIDE; HBRUSH hBrush = GetItemBtnBrush(hItem); HPEN hPen = GetItemBtnPen(hItem); HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hBrush); HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen); ::Polygon(hDC, pt, 3); ::SelectObject(hDC, hOldBrush); ::SelectObject(hDC, hOldPen); ::DeleteObject(hBrush); ::DeleteObject(hPen); } else { int nBottomOffset = (pRect->Height() - WIDE) / 2; POINT pt[3]; pt[0].x = pRect->right - ROFFSET - WIDE2; pt[0].y = pRect->bottom - nBottomOffset - WIDE; pt[1].x = pRect->right - ROFFSET - WIDE2; pt[1].y = pRect->bottom - nBottomOffset; pt[2].x = pRect->right - ROFFSET; pt[2].y = pRect->bottom - nBottomOffset - WIDE2; HBRUSH hBrush = GetItemBtnBrush(hItem); HPEN hPen = GetItemBtnPen(hItem); HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hBrush); HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen); ::Polygon(hDC, pt, 3); ::SelectObject(hDC, hOldBrush); ::SelectObject(hDC, hOldPen); ::DeleteObject(hBrush); ::DeleteObject(hPen); } } COLORREF CApredTreeCtrl2::SetBkColor(COLORREF crColor) { if (m_hBrushItem[0] != NULL) { ::DeleteObject(m_hBrushItem[0]); } m_hBrushItem[0] = CreateSolidBrush(crColor); return CTreeCtrl::SetBkColor(crColor); } int CApredTreeCtrl2::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CTreeCtrl::OnCreate(lpCreateStruct) == -1) return -1; m_crItemBk[0] = GetBkColor(); m_crItemBk[1] = GetSysColor(COLOR_HIGHLIGHT); m_hBrushItem[0] = CreateSolidBrush(m_crItemBk[0]); m_hBrushItem[1] = CreateSolidBrush(m_crItemBk[1]); m_hBrushItem[2] = CreateSolidBrush(m_crItemBk[2]); return 0; } HBRUSH CApredTreeCtrl2::GetItemBkBrush(HTREEITEM hItem) { BOOL bSelected = (GetItemState(hItem, TVIS_SELECTED) & TVIS_SELECTED) == TVIS_SELECTED; BOOL bHilited = (GetItemState(hItem, TVIS_DROPHILITED) & TVIS_DROPHILITED) == TVIS_DROPHILITED;; HTREEITEM hClickedItem = GetDropHilightItem(); if (bHilited) { return m_hBrushItem[1]; } if (!bSelected) { return m_hBrushItem[0]; } if (GetFocus() == this) { if (hClickedItem == NULL) { return m_hBrushItem[1]; } else { return m_hBrushItem[0]; } } return m_hBrushItem[2]; } HBRUSH CApredTreeCtrl2::GetItemBtnBrush(HTREEITEM hItem) { BOOL bExpanded = (GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED) == TVIS_EXPANDED; BOOL bSelected = (GetItemState(hItem, TVIS_SELECTED) & TVIS_SELECTED) == TVIS_SELECTED; BOOL bHilited = (GetItemState(hItem, TVIS_DROPHILITED) & TVIS_DROPHILITED) == TVIS_DROPHILITED;; HTREEITEM hClickedItem = GetDropHilightItem(); // Õ¹¿ªÊ±ÊµÐÄÈý½Ç if (bExpanded) { if (bHilited) { return CreateSolidBrush(m_crItemBtn[1]); } if (!bSelected) { return CreateSolidBrush(m_crItemBtn[0]); } if (GetFocus() == this && hClickedItem == NULL) { return CreateSolidBrush(m_crItemBtn[1]); } return CreateSolidBrush(m_crItemBtn[0]); } else { // ÊÕÆðʱ¿ÕÐÄÈý½Ç if (bHilited) { return CreateSolidBrush(m_crItemBk[1]); } if (!bSelected) { return CreateSolidBrush(m_crItemBk[0]); } if (GetFocus() == this && hClickedItem == NULL) { return CreateSolidBrush(m_crItemBk[1]); } return CreateSolidBrush(m_crItemBk[2]); } } HPEN CApredTreeCtrl2::GetItemBtnPen(HTREEITEM hItem) { BOOL bExpanded = (GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED) == TVIS_EXPANDED; BOOL bSelected = (GetItemState(hItem, TVIS_SELECTED) & TVIS_SELECTED) == TVIS_SELECTED; BOOL bHilited = (GetItemState(hItem, TVIS_DROPHILITED) & TVIS_DROPHILITED) == TVIS_DROPHILITED;; HTREEITEM hClickedItem = GetDropHilightItem(); // Õ¹¿ªÊ±ÊµÐÄÈý½Ç if (bExpanded) { if (bHilited) { return CreatePen(PS_SOLID, 1, m_crItemBtn[1]); } if (!bSelected) { return CreatePen(PS_SOLID, 1, m_crItemBtn[0]); } if (GetFocus() == this && hClickedItem == NULL) { return CreatePen(PS_SOLID, 1, m_crItemBtn[1]); } return CreatePen(PS_SOLID, 1, m_crItemBtn[0]); } else { // ÊÕÆðʱ¿ÕÐÄÈý½Ç if (bHilited) { return CreatePen(PS_SOLID, 1, m_crItemBtn[1]); } if (!bSelected) { return CreatePen(PS_SOLID, 1, m_crItemBtn[0]); } if (GetFocus() == this && hClickedItem == NULL) { return CreatePen(PS_SOLID, 1, m_crItemBtn[1]); } return CreatePen(PS_SOLID, 1, m_crItemBtn[0]); } } void CApredTreeCtrl2::PreSubclassWindow() { m_crItemBk[0] = GetBkColor(); m_crItemBk[1] = GetSysColor(COLOR_HIGHLIGHT); m_hBrushItem[0] = CreateSolidBrush(m_crItemBk[0]); m_hBrushItem[1] = CreateSolidBrush(m_crItemBk[1]); m_hBrushItem[2] = CreateSolidBrush(m_crItemBk[2]); CTreeCtrl::PreSubclassWindow(); } void CApredTreeCtrl2::SetItemBadge(HTREEITEM hItem, COLORREF badgeBackground, COLORREF badgeForeground) { if (m_badges.find(hItem) == m_badges.end()) { BADGE badge; badge.badgeBackground = badgeBackground; badge.badgeForeground = badgeForeground; badge.type = BADGE_HIDE; m_badges[hItem] = badge; } else { BADGE& badge = m_badges[hItem]; badge.badgeBackground = badgeBackground; badge.badgeForeground = badgeForeground; badge.type = BADGE_HIDE; } } void CApredTreeCtrl2::ShowItemBadgeNumber(HTREEITEM hItem, int number) { if (m_badges.find(hItem) == m_badges.end()) { return; } BADGE& badge = m_badges[hItem]; badge.type = BADGE_NUMBER; badge.number = number; InvalidateRect(NULL, TRUE); } void CApredTreeCtrl2::ShowItemBadgeDotMode(HTREEITEM hItem) { if (m_badges.find(hItem) == m_badges.end()) { return; } BADGE& badge = m_badges[hItem]; if (badge.type != BADGE_DOT) { badge.type = BADGE_DOT; InvalidateRect(NULL, TRUE); } } void CApredTreeCtrl2::HideItemBadge(HTREEITEM hItem) { if (m_badges.find(hItem) == m_badges.end()) { return; } BADGE& badge = m_badges[hItem]; if (badge.type != BADGE_HIDE) { badge.type = BADGE_HIDE; InvalidateRect(NULL, TRUE); } }