.h file:#if !defined(AFX_TREECTRLEX_H__572DF16F_9ECD_11D4_8A30_0000E8591EDF__INCLUDED_)
#define AFX_TREECTRLEX_H__572DF16F_9ECD_11D4_8A30_0000E8591EDF__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// TreeCtrlEx.h : header file
///////////////////////////////////////////////////////////////////////////////
// CTreeCtrlEx windowclass CTreeCtrlEx : public CTreeCtrl
{
// Construction
public:
CTreeCtrlEx();// Attributes
public:// Operations
public:// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTreeCtrlEx)
//}}AFX_VIRTUAL// Implementation
public:
int m_cyBitmap;
bool SetBkImage(LPCTSTR lpszResource);
bool SetBkImage(UINT nID);
virtual ~CTreeCtrlEx(); // Generated message map functions
protected:
int m_cxBitmap;
CBitmap m_bitmap;
//{{AFX_MSG(CTreeCtrlEx)
afx_msg void OnPaint();
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG DECLARE_MESSAGE_MAP()
};///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_TREECTRLEX_H__572DF16F_9ECD_11D4_8A30_0000E8591EDF__INCLUDED_)
.cpp file:
// TreeCtrlEx.cpp : implementation file
//#include "stdafx.h"
#include "test.h"
#include "TreeCtrlEx.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CTreeCtrlExCTreeCtrlEx::CTreeCtrlEx()
{
}CTreeCtrlEx::~CTreeCtrlEx()
{
}
BEGIN_MESSAGE_MAP(CTreeCtrlEx, CTreeCtrl)
//{{AFX_MSG_MAP(CTreeCtrlEx)
ON_WM_PAINT()
ON_WM_VSCROLL()
ON_WM_HSCROLL()
ON_WM_ERASEBKGND()
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CTreeCtrlEx message handlersvoid CTreeCtrlEx::OnPaint() 
{
if(m_bitmap.m_hObject == NULL)
{
CTreeCtrl::OnPaint();
return;
} CPaintDC dc(this); // device context for painting

// TODO: Add your message handler code here
CRect rcclip, rcclient;
dc.GetClipBox(&rcclip);
GetClientRect(&rcclient); CDC memdc;
memdc.CreateCompatibleDC(&dc); CBitmap bitmap, bmpimage;
bitmap.CreateCompatibleBitmap(&dc, rcclient.Width(), rcclient.Height());
memdc.SelectObject(&bitmap); CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC, 0);
// dc.BitBlt(rcclip.left, rcclip.top, rcclip.Width(), rcclip.Height(),
// &memdc, rcclip.left, rcclip.top, SRCCOPY);
// return; CDC maskdc;
maskdc.CreateCompatibleDC(&dc);
CBitmap maskbitmap;
maskbitmap.CreateBitmap(rcclient.Width(), rcclient.Height(), 1, 1, NULL);
maskdc.SelectObject(&maskbitmap); memdc.SetBkColor(::GetSysColor(COLOR_WINDOW)); maskdc.BitBlt(0, 0, rcclient.Width(), rcclient.Height(),
&memdc, rcclient.left, rcclient.top, SRCCOPY); CDC tempdc;
tempdc.CreateCompatibleDC(&dc);
CBitmap * pOld = tempdc.SelectObject(&m_bitmap); CDC imagedc;
imagedc.CreateCompatibleDC(&dc);
bmpimage.CreateCompatibleBitmap(&dc, rcclient.Width(), rcclient.Height());
imagedc.SelectObject(&bmpimage); CRect rcroot;
GetItemRect(GetRootItem(), rcroot, false);
rcroot.left = -GetScrollPos(SB_HORZ); for(int i = rcroot.left; i < rcclient.right; i+=m_cxBitmap)
for(int j = rcroot.top; j < rcclient.bottom; j += m_cyBitmap)
imagedc.BitBlt(i, j, m_cxBitmap, m_cyBitmap, &tempdc, 0, 0, SRCCOPY); // set the background of memdc to black. using srcpaint with black and any other 
// color results in the other color, thus making black the transparent color 
memdc.SetBkColor(RGB(0, 0, 0));
memdc.SetTextColor(RGB(255, 255, 255));
memdc.BitBlt(rcclip.left, rcclip.top, rcclip.Width(), rcclip.Height(), 
&maskdc, rcclip.left, rcclip.top, SRCCOPY); // set the foreground to black. see comment above.
imagedc.SetBkColor(RGB(255, 255, 255));
imagedc.SetTextColor(RGB(0, 0, 0));
imagedc.BitBlt(rcclip.left, rcclip.top, rcclip.Width(), rcclip.Height(),
&maskdc, rcclip.left, rcclip.top, SRCAND);
// combine the foreground with the background 
imagedc.BitBlt(rcclip.left, rcclip.top, rcclip.Width(), rcclip.Height(), 
&memdc, rcclip.left, rcclip.top, SRCPAINT); // Do not call CTreeCtrl::OnPaint() for painting messages
// draw the final image to the screen 
dc.BitBlt(rcclip.left, rcclip.top, rcclip.Width(), rcclip.Height(), 
&imagedc, rcclip.left, rcclip.top, SRCCOPY); tempdc.SelectObject(pOld);
}void CTreeCtrlEx::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
// TODO: Add your message handler code here and/or call default
if(m_bitmap.m_hObject) InvalidateRect(NULL);

CTreeCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}void CTreeCtrlEx::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
// TODO: Add your message handler code here and/or call default
if(m_bitmap.m_hObject) InvalidateRect(NULL);

CTreeCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}BOOL CTreeCtrlEx::OnEraseBkgnd(CDC* pDC) 
{
// TODO: Add your message handler code here and/or call default
if(m_bitmap.m_hObject) return TRUE;

return CTreeCtrl::OnEraseBkgnd(pDC);
}void CTreeCtrlEx::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) 
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
if(m_bitmap.m_hObject) InvalidateRect(NULL);

*pResult = 0;
}bool CTreeCtrlEx::SetBkImage(UINT nID)
{
return SetBkImage(LPCTSTR(nID));
}bool CTreeCtrlEx::SetBkImage(LPCTSTR lpszResource)
{
if(m_bitmap.m_hObject != NULL)
m_bitmap.DeleteObject(); HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
lpszResource, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); if(!hBmp) return false; m_bitmap.Attach(hBmp); BITMAP bm;
m_bitmap.GetBitmap(&bm);
m_cxBitmap = bm.bmWidth;
m_cyBitmap = bm.bmHeight; Invalidate();
return true;
}