Click here to Skip to main content
15,888,527 members
Articles / Desktop Programming / MFC

XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop

Rate me:
Please Sign up or sign in to vote.
4.97/5 (164 votes)
1 Jan 2008CPOL22 min read 455.8K   10.1K   372  
XHtmlTree is an MFC control based on CTreeCtrl, with support for HTML text, web links, APP: links, XML load/save, Smart Checkboxes, and Drag & Drop.
// CreateCheckboxImageList.cpp  Version 1.0
//
// Author:  Hans Dietrich
//          hdietrich@gmail.com
//
// History
//     Version 1.0 - 2007 July 15
//     - Initial public release
//
// License:
//     This software is released into the public domain.  You are free to use
//     it in any way you like, except that you may not sell this source code.
//
//     This software is provided "as is" with no expressed or implied warranty.
//     I accept no liability for any damage or loss of business that this 
//     software may cause.
//
///////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "CreateCheckboxImageList.h"
#include "visualstylesxp.h"

namespace HDCheckboxImageList
{

///////////////////////////////////////////////////////////////////////////////
//
// CreateCheckboxImageList()
//
// Purpose:     Create themed checkbox image list
//
// Parameters:  pDC          - pointer to device context for drawing
//              imagelist    - image list to create
//              nSize        - height and width of images
//              crBackground - fill color
//
// Returns:     BOOL         - TRUE if image list created OK
//
BOOL CreateCheckboxImageList(CDC *pDC, 
							 CImageList& imagelist, 
							 int nSize, 
							 COLORREF crBackground)
{
	ASSERT(pDC);
	ASSERT(nSize > 0);

	BOOL rc = FALSE;

	///////////////////////////////////////////////////////////////////////////
	//
	// CHECKBOX IMAGES
	//
	// From MSDN:  "To indicate that the item has no state image, set the
	//             index to zero. This convention means that image zero in 
	//             the state image list cannot be used as a state image."
	//
	// Note that comparable hot image = cold image index OR 8.
	// Disabled state = index OR 4.
	
	struct CHECKBOXDRAWDATA
	{
		TCHAR * pszDesc;	// description for debugging
		int nStateId;		// for DrawThemeBackground
		UINT nState;		// for DrawFrameControl
	} 
	cbdd[] =
	{
		// cold -----------------------------------------------------------------------------------
/*0000*/_T("unused"),				0,						0,
/*0001*/_T("unchecked normal"),		CBS_UNCHECKEDNORMAL,	DFCS_BUTTONCHECK | DFCS_FLAT,
/*0010*/_T("checked normal"),		CBS_CHECKEDNORMAL,		DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_FLAT,
/*0011*/_T("tri-state normal"),		CBS_MIXEDNORMAL,		DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_FLAT,
/*0100*/_T("unused"),				0,						0,
/*0101*/_T("unchecked disabled"),	CBS_UNCHECKEDDISABLED,	DFCS_BUTTONCHECK | DFCS_INACTIVE | DFCS_FLAT,
/*0110*/_T("checked disabled"),		CBS_CHECKEDDISABLED,	DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_INACTIVE | DFCS_FLAT,
/*0111*/_T("tri-state disabled"),	CBS_MIXEDDISABLED,		DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_INACTIVE | DFCS_FLAT,

		// hot ------------------------------------------------------------------------------------
/*1000*/_T("unused"),				0,						0,
/*1001*/_T("unchecked normal"),		CBS_UNCHECKEDHOT,		DFCS_BUTTONCHECK | DFCS_FLAT,
/*1010*/_T("checked normal"),		CBS_CHECKEDHOT,			DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_FLAT,
/*1011*/_T("tri-state normal"),		CBS_MIXEDHOT,			DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_FLAT,
/*1100*/_T("unused"),				0,						0,
/*1101*/_T("unchecked disabled"),	CBS_UNCHECKEDDISABLED,	DFCS_BUTTONCHECK | DFCS_INACTIVE | DFCS_FLAT,
/*1110*/_T("checked disabled"),		CBS_CHECKEDDISABLED,	DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_INACTIVE | DFCS_FLAT,
/*1111*/_T("tri-state disabled"),	CBS_MIXEDDISABLED,		DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_INACTIVE | DFCS_FLAT,

		NULL, 0, 0		// last entry
	};

	if (pDC && (nSize > 0))
	{
		const int nBmpWidth = nSize;
		const int nBmpHeight = nSize;
		const int nImages = sizeof(cbdd)/sizeof(cbdd[0]);
		ASSERT(nImages == 17);

		if (imagelist.GetSafeHandle())
			imagelist.DeleteImageList();

		CBitmap bmpCheckboxes;

		if (bmpCheckboxes.CreateCompatibleBitmap(pDC, nBmpWidth * nImages, 
				nBmpHeight))
		{
			if (imagelist.Create(nBmpWidth, nBmpHeight, ILC_COLOR32 | ILC_MASK, 
					nImages, 1))
			{
				CDC dcMem;
				if (dcMem.CreateCompatibleDC(pDC))
				{
					HTHEME hTheme = NULL;
					hTheme = (g_xpStyle.IsThemeActive() && 
							  g_xpStyle.IsAppThemed()) ? 
							  g_xpStyle.OpenThemeData(NULL, L"BUTTON") : NULL;
					CBitmap* pOldBmp = dcMem.SelectObject(&bmpCheckboxes);
					dcMem.FillSolidRect(0, 0, nBmpWidth*nImages, nBmpHeight, 
						crBackground);

					int nImageWidth  = nBmpWidth - 2;		// allow 2 for border
					int nImageHeight = nBmpHeight - 2;
					int nImageLeft   = (nBmpWidth - nImageWidth) / 2;
					int nImageTop    = (nBmpHeight - nImageHeight) / 2;

					CRect rectImage(nImageLeft, 
									nImageTop, 
									nImageLeft+nImageWidth, 
									nImageTop+nImageHeight);

					for (int i = 0; cbdd[i].pszDesc != NULL; i++)
					{
						if (_tcscmp(cbdd[i].pszDesc, _T("unused")) == 0)
						{
							// unused image slot
							// note that we skip the first image - they are 1-based
						}
						else
						{
							if (hTheme)
							{
								g_xpStyle.DrawThemeBackground(hTheme, dcMem, 
									BP_CHECKBOX, cbdd[i].nStateId, &rectImage, 
									NULL);
								g_xpStyle.DrawThemeEdge(hTheme, dcMem, 
									BP_CHECKBOX, cbdd[i].nStateId, &rectImage, 0, 0, 
									NULL);
							}
							else
							{
								dcMem.DrawFrameControl(&rectImage, DFC_BUTTON, 
									cbdd[i].nState);
							}
						}

						rectImage.left  += nBmpWidth;
						rectImage.right += nBmpWidth;
					}

					if (hTheme)
					{
						g_xpStyle.CloseThemeData(hTheme);
						hTheme = NULL;
					}

					dcMem.SelectObject(pOldBmp);
					imagelist.Add(&bmpCheckboxes, RGB(255,0,255));
					if (hTheme)
						g_xpStyle.CloseThemeData(hTheme);

					rc = TRUE;
				}
				else
				{
					TRACE(_T("ERROR - failed to create DC\n"));
				}
			}
			else
			{
				TRACE(_T("ERROR - failed to create image list\n"));
			}
		}
		else
		{
			TRACE(_T("ERROR - failed to create bitmap\n"));
		}
	}
	else
	{
		TRACE(_T("ERROR - bad parameters\n"));
	}
	return rc;
}

}	// namespace

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Hans Dietrich Software
United States United States
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.

Recently, I have moved to Los Angeles where I am doing consulting and development work.

For consulting and custom software development, please see www.hdsoft.org.






Comments and Discussions