/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2001-2002 by David Yuheng Zhao
//
// Distribute and change freely, except: don't remove my name from the source 
//
// No warrantee of any kind, express or implied, is included with this
// software; use at your own risk, responsibility for damages (if any) to
// anyone resulting from the use of this software rests entirely with the
// user.
//
// Partly based on the _ThemeHelper struct in MFC7.0 source code (winctrl3.cpp), 
// and the difference is that this implementation wraps the full set of 
// visual style APIs from the platform SDK August 2001
//
// If you have any questions, I can be reached as follows:
//	yuheng_zhao@yahoo.com
//
//
// How to use:
// Instead of calling the API directly, 
//    OpenThemeData(...);
// use the global variable
//    g_xpStyle.OpenThemeData(...);
//
/////////////////////////////////////////////////////////////////////////////

#include "visualstylesxp.h"


CVisualStylesXP g_xpStyle;

CVisualStylesXP::CVisualStylesXP(void)
{
	m_hThemeDll = LoadLibrary(_T("UxTheme.dll"));
}

CVisualStylesXP::~CVisualStylesXP(void)
{
	if (m_hThemeDll!=NULL)
		FreeLibrary(m_hThemeDll);
	m_hThemeDll = NULL;
}

void* CVisualStylesXP::GetProc(LPCSTR szProc, void* pfnFail)
{
	void* pRet = pfnFail;
	if (m_hThemeDll != NULL)
		pRet = GetProcAddress(m_hThemeDll, szProc);
	return pRet;
}

HTHEME CVisualStylesXP::OpenThemeData(HWND hwnd, LPCWSTR pszClassList)
{
	PFNOPENTHEMEDATA pfnOpenThemeData = (PFNOPENTHEMEDATA)GetProc("OpenThemeData", (void*)OpenThemeDataFail);
	return (*pfnOpenThemeData)(hwnd, pszClassList);
}

HRESULT CVisualStylesXP::CloseThemeData(HTHEME hTheme)
{
	PFNCLOSETHEMEDATA pfnCloseThemeData = (PFNCLOSETHEMEDATA)GetProc("CloseThemeData", (void*)CloseThemeDataFail);
	return (*pfnCloseThemeData)(hTheme);
}

HRESULT CVisualStylesXP::DrawThemeBackground(HTHEME hTheme, HDC hdc, 
											 int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect)
{
	PFNDRAWTHEMEBACKGROUND pfnDrawThemeBackground = 
		(PFNDRAWTHEMEBACKGROUND)GetProc("DrawThemeBackground", (void*)DrawThemeBackgroundFail);
	return (*pfnDrawThemeBackground)(hTheme, hdc, iPartId, iStateId, pRect, pClipRect);
}


HRESULT CVisualStylesXP::DrawThemeText(HTHEME hTheme, HDC hdc, int iPartId, 
									   int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, 
									   DWORD dwTextFlags2, const RECT *pRect)
{
	PFNDRAWTHEMETEXT pfn = (PFNDRAWTHEMETEXT)GetProc("DrawThemeText", (void*)DrawThemeTextFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, pRect);
}
HRESULT CVisualStylesXP::GetThemeBackgroundContentRect(HTHEME hTheme,  HDC hdc, 
													   int iPartId, int iStateId,  const RECT *pBoundingRect, 
													   RECT *pContentRect)
{
	PFNGETTHEMEBACKGROUNDCONTENTRECT pfn = (PFNGETTHEMEBACKGROUNDCONTENTRECT)GetProc("GetThemeBackgroundContentRect", (void*)GetThemeBackgroundContentRectFail);
	return (*pfn)(hTheme,  hdc, iPartId, iStateId,  pBoundingRect, pContentRect);
}
HRESULT CVisualStylesXP::GetThemeBackgroundExtent(HTHEME hTheme,  HDC hdc,
												  int iPartId, int iStateId, const RECT *pContentRect, 
												  RECT *pExtentRect)
{
	PFNGETTHEMEBACKGROUNDEXTENT pfn = (PFNGETTHEMEBACKGROUNDEXTENT)GetProc("GetThemeBackgroundExtent", (void*)GetThemeBackgroundExtentFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId, pContentRect, pExtentRect);
}
HRESULT CVisualStylesXP::GetThemePartSize(HTHEME hTheme, HDC hdc, 
										  int iPartId, int iStateId, RECT * pRect, enum THEMESIZE eSize, SIZE *psz)
{
	PFNGETTHEMEPARTSIZE pfnGetThemePartSize = 
		(PFNGETTHEMEPARTSIZE)GetProc("GetThemePartSize", (void*)GetThemePartSizeFail);
	return (*pfnGetThemePartSize)(hTheme, hdc, iPartId, iStateId, pRect, eSize, psz);
}

HRESULT CVisualStylesXP::GetThemeTextExtent(HTHEME hTheme, HDC hdc, 
											int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, 
											DWORD dwTextFlags,  const RECT *pBoundingRect, 
											RECT *pExtentRect)
{
	PFNGETTHEMETEXTEXTENT pfn = (PFNGETTHEMETEXTEXTENT)GetProc("GetThemeTextExtent", (void*)GetThemeTextExtentFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags,  pBoundingRect, pExtentRect);
}

HRESULT CVisualStylesXP::GetThemeTextMetrics(HTHEME hTheme,  HDC hdc, 
											 int iPartId, int iStateId,  TEXTMETRIC* ptm)
{
	PFNGETTHEMETEXTMETRICS pfn = (PFNGETTHEMETEXTMETRICS)GetProc("GetThemeTextMetrics", (void*)GetThemeTextMetricsFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId,  ptm);
}

HRESULT CVisualStylesXP::GetThemeBackgroundRegion(HTHEME hTheme,  HDC hdc,  
												  int iPartId, int iStateId, const RECT *pRect,  HRGN *pRegion)
{
	PFNGETTHEMEBACKGROUNDREGION pfn = (PFNGETTHEMEBACKGROUNDREGION)GetProc("GetThemeBackgroundRegion", (void*)GetThemeBackgroundRegionFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId, pRect, pRegion);
}

HRESULT CVisualStylesXP::HitTestThemeBackground(HTHEME hTheme,  HDC hdc, int iPartId, 
												int iStateId, DWORD dwOptions, const RECT *pRect,  HRGN hrgn, 
												POINT ptTest,  WORD *pwHitTestCode)
{
	PFNHITTESTTHEMEBACKGROUND pfn = (PFNHITTESTTHEMEBACKGROUND)GetProc("HitTestThemeBackground", (void*)HitTestThemeBackgroundFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId, dwOptions, pRect, hrgn, ptTest, pwHitTestCode);
}

HRESULT CVisualStylesXP::DrawThemeEdge(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, 
									   const RECT *pDestRect, UINT uEdge, UINT uFlags,   RECT *pContentRect)
{
	PFNDRAWTHEMEEDGE pfn = (PFNDRAWTHEMEEDGE)GetProc("DrawThemeEdge", (void*)DrawThemeEdgeFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId, pDestRect, uEdge, uFlags, pContentRect);
}

HRESULT CVisualStylesXP::DrawThemeIcon(HTHEME hTheme, HDC hdc, int iPartId, 
									   int iStateId, const RECT *pRect, HIMAGELIST himl, int iImageIndex)
{
	PFNDRAWTHEMEICON pfn = (PFNDRAWTHEMEICON)GetProc("DrawThemeIcon", (void*)DrawThemeIconFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId, pRect, himl, iImageIndex);
}

BOOL CVisualStylesXP::IsThemePartDefined(HTHEME hTheme, int iPartId, 
										 int iStateId)
{
	PFNISTHEMEPARTDEFINED pfn = (PFNISTHEMEPARTDEFINED)GetProc("IsThemePartDefined", (void*)IsThemePartDefinedFail);
	return (*pfn)(hTheme, iPartId, iStateId);
}

BOOL CVisualStylesXP::IsThemeBackgroundPartiallyTransparent(HTHEME hTheme, 
															int iPartId, int iStateId)
{
	PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT pfn = (PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT)GetProc("IsThemeBackgroundPartiallyTransparent", (void*)IsThemeBackgroundPartiallyTransparentFail);
	return (*pfn)(hTheme, iPartId, iStateId);
}

HRESULT CVisualStylesXP::GetThemeColor(HTHEME hTheme, int iPartId, 
									   int iStateId, int iPropId,  COLORREF *pColor)
{
	PFNGETTHEMECOLOR pfn = (PFNGETTHEMECOLOR)GetProc("GetThemeColor", (void*)GetThemeColorFail);
	return (*pfn)(hTheme, iPartId, iStateId, iPropId, pColor);
}

HRESULT CVisualStylesXP::GetThemeMetric(HTHEME hTheme,  HDC hdc, int iPartId, 
										int iStateId, int iPropId,  int *piVal)
{
	PFNGETTHEMEMETRIC pfn = (PFNGETTHEMEMETRIC)GetProc("GetThemeMetric", (void*)GetThemeMetricFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId, iPropId, piVal);
}

HRESULT CVisualStylesXP::GetThemeString(HTHEME hTheme, int iPartId, 
										int iStateId, int iPropId,  LPWSTR pszBuff, int cchMaxBuffChars)
{
	PFNGETTHEMESTRING pfn = (PFNGETTHEMESTRING)GetProc("GetThemeString", (void*)GetThemeStringFail);
	return (*pfn)(hTheme, iPartId, iStateId, iPropId, pszBuff, cchMaxBuffChars);
}

HRESULT CVisualStylesXP::GetThemeBool(HTHEME hTheme, int iPartId, 
									  int iStateId, int iPropId,  BOOL *pfVal)
{
	PFNGETTHEMEBOOL pfn = (PFNGETTHEMEBOOL)GetProc("GetThemeBool", (void*)GetThemeBoolFail);
	return (*pfn)(hTheme, iPartId, iStateId, iPropId, pfVal);
}

HRESULT CVisualStylesXP::GetThemeInt(HTHEME hTheme, int iPartId, 
									 int iStateId, int iPropId,  int *piVal)
{
	PFNGETTHEMEINT pfn = (PFNGETTHEMEINT)GetProc("GetThemeInt", (void*)GetThemeIntFail);
	return (*pfn)(hTheme, iPartId, iStateId, iPropId, piVal);
}

HRESULT CVisualStylesXP::GetThemeEnumValue(HTHEME hTheme, int iPartId, 
										   int iStateId, int iPropId,  int *piVal)
{
	PFNGETTHEMEENUMVALUE pfn = (PFNGETTHEMEENUMVALUE)GetProc("GetThemeEnumValue", (void*)GetThemeEnumValueFail);
	return (*pfn)(hTheme, iPartId, iStateId, iPropId, piVal);
}

HRESULT CVisualStylesXP::GetThemePosition(HTHEME hTheme, int iPartId, 
										  int iStateId, int iPropId,  POINT *pPoint)
{
	PFNGETTHEMEPOSITION pfn = (PFNGETTHEMEPOSITION)GetProc("GetThemePosition", (void*)GetThemePositionFail);
	return (*pfn)(hTheme, iPartId, iStateId, iPropId, pPoint);
}

HRESULT CVisualStylesXP::GetThemeFont(HTHEME hTheme,  HDC hdc, int iPartId, 
									  int iStateId, int iPropId,  LOGFONT *pFont)
{
	PFNGETTHEMEFONT pfn = (PFNGETTHEMEFONT)GetProc("GetThemeFont", (void*)GetThemeFontFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId, iPropId, pFont);
}

HRESULT CVisualStylesXP::GetThemeRect(HTHEME hTheme, int iPartId, 
									  int iStateId, int iPropId,  RECT *pRect)
{
	PFNGETTHEMERECT pfn = (PFNGETTHEMERECT)GetProc("GetThemeRect", (void*)GetThemeRectFail);
	return (*pfn)(hTheme, iPartId, iStateId, iPropId, pRect);
}

HRESULT CVisualStylesXP::GetThemeMargins(HTHEME hTheme,  HDC hdc, int iPartId, 
										 int iStateId, int iPropId,  RECT *prc,  MARGINS *pMargins)
{
	PFNGETTHEMEMARGINS pfn = (PFNGETTHEMEMARGINS)GetProc("GetThemeMargins", (void*)GetThemeMarginsFail);
	return (*pfn)(hTheme, hdc, iPartId, iStateId, iPropId, prc, pMargins);
}

HRESULT CVisualStylesXP::GetThemeIntList(HTHEME hTheme, int iPartId, 
										 int iStateId, int iPropId,  INTLIST *pIntList)
{
	PFNGETTHEMEINTLIST pfn = (PFNGETTHEMEINTLIST)GetProc("GetThemeIntList", (void*)GetThemeIntListFail);
	return (*pfn)(hTheme, iPartId, iStateId, iPropId, pIntList);
}

HRESULT CVisualStylesXP::GetThemePropertyOrigin(HTHEME hTheme, int iPartId, 
												int iStateId, int iPropId,  enum PROPERTYORIGIN *pOrigin)
{
	PFNGETTHEMEPROPERTYORIGIN pfn = (PFNGETTHEMEPROPERTYORIGIN)GetProc("GetThemePropertyOrigin", (void*)GetThemePropertyOriginFail);
	return (*pfn)(hTheme, iPartId, iStateId, iPropId, pOrigin);
}

HRESULT CVisualStylesXP::SetWindowTheme(HWND hwnd, LPCWSTR pszSubAppName, 
										LPCWSTR pszSubIdList)
{
	PFNSETWINDOWTHEME pfn = (PFNSETWINDOWTHEME)GetProc("SetWindowTheme", (void*)SetWindowThemeFail);
	return (*pfn)(hwnd, pszSubAppName, pszSubIdList);
}

HRESULT CVisualStylesXP::GetThemeFilename(HTHEME hTheme, int iPartId, 
										  int iStateId, int iPropId,  LPWSTR pszThemeFileName, int cchMaxBuffChars)
{
	PFNGETTHEMEFILENAME pfn = (PFNGETTHEMEFILENAME)GetProc("GetThemeFilename", (void*)GetThemeFilenameFail);
	return (*pfn)(hTheme, iPartId, iStateId, iPropId,  pszThemeFileName, cchMaxBuffChars);
}

COLORREF CVisualStylesXP::GetThemeSysColor(HTHEME hTheme, int iColorId)
{
	PFNGETTHEMESYSCOLOR pfn = (PFNGETTHEMESYSCOLOR)GetProc("GetThemeSysColor", (void*)GetThemeSysColorFail);
	return (*pfn)(hTheme, iColorId);
}

HBRUSH CVisualStylesXP::GetThemeSysColorBrush(HTHEME hTheme, int iColorId)
{
	PFNGETTHEMESYSCOLORBRUSH pfn = (PFNGETTHEMESYSCOLORBRUSH)GetProc("GetThemeSysColorBrush", (void*)GetThemeSysColorBrushFail);
	return (*pfn)(hTheme, iColorId);
}

BOOL CVisualStylesXP::GetThemeSysBool(HTHEME hTheme, int iBoolId)
{
	PFNGETTHEMESYSBOOL pfn = (PFNGETTHEMESYSBOOL)GetProc("GetThemeSysBool", (void*)GetThemeSysBoolFail);
	return (*pfn)(hTheme, iBoolId);
}

int CVisualStylesXP::GetThemeSysSize(HTHEME hTheme, int iSizeId)
{
	PFNGETTHEMESYSSIZE pfn = (PFNGETTHEMESYSSIZE)GetProc("GetThemeSysSize", (void*)GetThemeSysSizeFail);
	return (*pfn)(hTheme, iSizeId);
}

HRESULT CVisualStylesXP::GetThemeSysFont(HTHEME hTheme, int iFontId,  LOGFONT *plf)
{
	PFNGETTHEMESYSFONT pfn = (PFNGETTHEMESYSFONT)GetProc("GetThemeSysFont", (void*)GetThemeSysFontFail);
	return (*pfn)(hTheme, iFontId, plf);
}

HRESULT CVisualStylesXP::GetThemeSysString(HTHEME hTheme, int iStringId, 
										   LPWSTR pszStringBuff, int cchMaxStringChars)
{
	PFNGETTHEMESYSSTRING pfn = (PFNGETTHEMESYSSTRING)GetProc("GetThemeSysString", (void*)GetThemeSysStringFail);
	return (*pfn)(hTheme, iStringId, pszStringBuff, cchMaxStringChars);
}

HRESULT CVisualStylesXP::GetThemeSysInt(HTHEME hTheme, int iIntId, int *piValue)
{
	PFNGETTHEMESYSINT pfn = (PFNGETTHEMESYSINT)GetProc("GetThemeSysInt", (void*)GetThemeSysIntFail);
	return (*pfn)(hTheme, iIntId, piValue);
}

BOOL CVisualStylesXP::IsThemeActive()
{
	PFNISTHEMEACTIVE pfn = (PFNISTHEMEACTIVE)GetProc("IsThemeActive", (void*)IsThemeActiveFail);
	return (*pfn)();
}

BOOL CVisualStylesXP::IsAppThemed()
{
	PFNISAPPTHEMED pfnIsAppThemed = (PFNISAPPTHEMED)GetProc("IsAppThemed", (void*)IsAppThemedFail);
	return (*pfnIsAppThemed)();
}

HTHEME CVisualStylesXP::GetWindowTheme(HWND hwnd)
{
	PFNGETWINDOWTHEME pfn = (PFNGETWINDOWTHEME)GetProc("GetWindowTheme", (void*)GetWindowThemeFail);
	return (*pfn)(hwnd);
}

HRESULT CVisualStylesXP::EnableThemeDialogTexture(HWND hwnd, DWORD dwFlags)
{
	PFNENABLETHEMEDIALOGTEXTURE pfn = (PFNENABLETHEMEDIALOGTEXTURE)GetProc("EnableThemeDialogTexture", (void*)EnableThemeDialogTextureFail);
	return (*pfn)(hwnd, dwFlags);
}

BOOL CVisualStylesXP::IsThemeDialogTextureEnabled(HWND hwnd)
{
	PFNISTHEMEDIALOGTEXTUREENABLED pfn = (PFNISTHEMEDIALOGTEXTUREENABLED)GetProc("IsThemeDialogTextureEnabled", (void*)IsThemeDialogTextureEnabledFail);
	return (*pfn)(hwnd);
}

DWORD CVisualStylesXP::GetThemeAppProperties()
{
	PFNGETTHEMEAPPPROPERTIES pfn = (PFNGETTHEMEAPPPROPERTIES)GetProc("GetThemeAppProperties", (void*)GetThemeAppPropertiesFail);
	return (*pfn)();
}

void CVisualStylesXP::SetThemeAppProperties(DWORD dwFlags)
{
	PFNSETTHEMEAPPPROPERTIES pfn = (PFNSETTHEMEAPPPROPERTIES)GetProc("SetThemeAppProperties", (void*)SetThemeAppPropertiesFail);
	(*pfn)(dwFlags);
}

HRESULT CVisualStylesXP::GetCurrentThemeName(
	LPWSTR pszThemeFileName, int cchMaxNameChars, 
	LPWSTR pszColorBuff, int cchMaxColorChars,
	LPWSTR pszSizeBuff, int cchMaxSizeChars)
{
	PFNGETCURRENTTHEMENAME pfn = (PFNGETCURRENTTHEMENAME)GetProc("GetCurrentThemeName", (void*)GetCurrentThemeNameFail);
	return (*pfn)(pszThemeFileName, cchMaxNameChars, pszColorBuff, cchMaxColorChars, pszSizeBuff, cchMaxSizeChars);
}

HRESULT CVisualStylesXP::GetThemeDocumentationProperty(LPCWSTR pszThemeName,
													   LPCWSTR pszPropertyName,  LPWSTR pszValueBuff, int cchMaxValChars)
{
	PFNGETTHEMEDOCUMENTATIONPROPERTY pfn = (PFNGETTHEMEDOCUMENTATIONPROPERTY)GetProc("GetThemeDocumentationProperty", (void*)GetThemeDocumentationPropertyFail);
	return (*pfn)(pszThemeName, pszPropertyName, pszValueBuff, cchMaxValChars);
}

						 
HRESULT CVisualStylesXP::DrawThemeParentBackground(HWND hwnd, HDC hdc,  RECT* prc)
{
	PFNDRAWTHEMEPARENTBACKGROUND pfn = (PFNDRAWTHEMEPARENTBACKGROUND)GetProc("DrawThemeParentBackground", (void*)DrawThemeParentBackgroundFail);
	return (*pfn)(hwnd, hdc, prc);
}

HRESULT CVisualStylesXP::EnableTheming(BOOL fEnable)
{
	PFNENABLETHEMING pfn = (PFNENABLETHEMING)GetProc("EnableTheming", (void*)EnableThemingFail);
	return (*pfn)(fEnable);
}


#if 0 //someday we may want to draw fancy bitmap buttons, but not today
/*
// local functions
static int image_left (int cx, const RECT& Rect, DWORD style);
static int image_top (int cy, const RECT& Rect, DWORD style);
static void draw_bitmap (HDC hDC, HWND hWnd, const RECT& Rect, DWORD style);
static void draw_icon (HDC hDC, HWND hWnd,  const RECT& Rect, DWORD style);
static void draw_text (HDC hDC, HWND hWnd, const RECT& Rect, DWORD style);


// CImageButtonWithStyle

//Handle NM_CUSTOMDRAW notifications.
// If an XP visual styles theme is active, use the uxtheme.dll functions
// ti draw buttons with BS_BITMAP or BS_ICON style so that they match the
// appearance of normal text buttons.
LRESULT ProcessButtonDrawMessage(HWND hButton, NMHDR * pNotifyStruct)
{ 

	LRESULT result = 0;
	LPNMCUSTOMDRAW pCustomDraw = (LPNMCUSTOMDRAW) pNotifyStruct;

	DWORD style = GetWindowLongPtr(hButton, GWL_STYLE);
	if (  !g_xpStyle.IsAppThemed () || !g_xpStyle.IsThemeActive ())
	{
		// not icon or bitmap button, or themes not active - draw normally
		result = CDRF_DODEFAULT;
		return result;
	}

	if (pCustomDraw->dwDrawStage == CDDS_PREERASE)
	{
		// erase background (according to parent window's themed background
		g_xpStyle.DrawThemeParentBackground (hButton, pCustomDraw->hdc, &pCustomDraw->rc);
	}

	if (pCustomDraw->dwDrawStage == CDDS_PREERASE || pCustomDraw->dwDrawStage == CDDS_PREPAINT)
	{
		// get theme handle
		HTHEME hTheme = g_xpStyle.OpenThemeData (hButton, L"BUTTON");
		assert (hTheme != NULL);
		if (hTheme == NULL)
		{
			// fail gracefully
			return CDRF_DODEFAULT;
		}

		// determine state for DrawThemeBackground()
		// note: order of these tests is significant
		int state_id = PBS_NORMAL;
		if (style & WS_DISABLED)
			state_id = PBS_DISABLED;
		else if (pCustomDraw->uItemState & CDIS_SELECTED)
			state_id = PBS_PRESSED;
		else if (pCustomDraw->uItemState & CDIS_HOT)
			state_id = PBS_HOT;
		else if (style & BS_DEFPUSHBUTTON)
			state_id = PBS_DEFAULTED;

		// draw themed button background appropriate to button state
		g_xpStyle.DrawThemeBackground (hTheme,
			pCustomDraw->hdc, BP_PUSHBUTTON,
			state_id,
			&pCustomDraw->rc, NULL);

		// get content rectangle (space inside button for image)
		RECT content_rect;
		CopyRect( &content_rect, &pCustomDraw->rc); 
		g_xpStyle.GetThemeBackgroundContentRect (hTheme,
			pCustomDraw->hdc, BP_PUSHBUTTON,
			state_id,
			&pCustomDraw->rc,
			&content_rect);
		// we're done with the theme
		g_xpStyle.CloseThemeData(hTheme);

		// draw the image
		if (style & BS_BITMAP)
		{
			draw_bitmap (pCustomDraw->hdc, hButton, content_rect, style);
		}
		else if (style & BS_ICON)
		{
			draw_icon (pCustomDraw->hdc, hButton, content_rect, style);
		}
		else
		{
			draw_text (pCustomDraw->hdc, hButton, content_rect, style);
		}

		// finally, draw the focus rectangle if needed
		if (pCustomDraw->uItemState & CDIS_FOCUS)
		{
			// draw focus rectangle
			DrawFocusRect (pCustomDraw->hdc, &content_rect);
		}

		return CDRF_SKIPDEFAULT;
	}

	// we should never get here, since we should only get CDDS_PREERASE or CDDS_PREPAINT
	//assert (false);

	return CDRF_DODEFAULT;
}

// draw_bitmap () - Draw a bitmap
void draw_bitmap (HDC hDC, HWND hWnd, const RECT& Rect, DWORD style)
{
	HBITMAP hBitmap = (HBITMAP)::SendMessage(hWnd, BM_GETIMAGE, IMAGE_BITMAP, 0L);
	if (hBitmap == NULL)
		return;

	// determine size of bitmap image
	BITMAPINFO bmi;
	memset (&bmi, 0, sizeof (BITMAPINFO));
	bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
	GetDIBits(hDC, hBitmap, 0, 0, NULL, &bmi, DIB_RGB_COLORS);

	// determine position of top-left corner of bitmap (positioned according to style)
	int x = image_left (bmi.bmiHeader.biWidth, Rect, style);
	int y = image_top (bmi.bmiHeader.biHeight, Rect, style);

	// Draw the bitmap
	DrawState(hDC, NULL, NULL, (LPARAM) hBitmap, 0, x, y, bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight,
		(style & WS_DISABLED) != 0 ? (DST_BITMAP | DSS_DISABLED) : (DST_BITMAP | DSS_NORMAL));
}

// draw_icon () - Draw an icon
void draw_icon (HDC hDC, HWND hWnd,  const RECT& Rect, DWORD style)
{
	HICON hIcon = (HICON)::SendMessage(hWnd, WM_GETICON, 1, 0);
	if (hIcon == NULL)
		return;

	// determine size of icon image
	ICONINFO ii;
	GetIconInfo (hIcon, &ii);
	BITMAPINFO bmi;
	memset (&bmi, 0, sizeof (BITMAPINFO));
	bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
	int cx = 0;
	int cy = 0;
	if (ii.hbmColor != NULL)
	{
		// icon has separate image and mask bitmaps - use size directly
		GetDIBits(hDC, ii.hbmColor, 0, 0, NULL, &bmi, DIB_RGB_COLORS);
		cx = bmi.bmiHeader.biWidth;
		cy = bmi.bmiHeader.biHeight;
	}
	else
	{
		// icon has singel mask bitmap which is twice as high as icon
		GetDIBits(hDC, ii.hbmMask, 0, 0, NULL, &bmi, DIB_RGB_COLORS);
		cx = bmi.bmiHeader.biWidth;
		cy = bmi.bmiHeader.biHeight/2;
	}

	// determine position of top-left corner of icon
	int x = image_left (cx, Rect, style);
	int y = image_top (cy, Rect, style);

	// Draw the icon
	DrawState(hDC, NULL, NULL, (LPARAM) hIcon, 0, x, y, cx, cy,
		(style & WS_DISABLED) != 0 ? (DST_ICON | DSS_DISABLED) : (DST_ICON | DSS_NORMAL));
}

// draw_text () - Draw text
void draw_text (HDC hDC, HWND hWnd, const RECT& Rect, DWORD style)
{
	
	//The image is text. The lData parameter is a pointer to the string, 
	//and the wData parameter specifies the length. If wData is zero, 
	//the string must be null-terminated.
	TCHAR *pText = NULL;
	int nLen = ::SendMessage(hWnd, WM_GETTEXTLENGTH, 0,0);
	if (nLen > 0)
	{
		pText = new TCHAR[nLen +1];
		::SendMessage(hWnd, WM_GETTEXT, nLen+1, (LPARAM)pText );
		pText[nLen] = _T('\0'); 
	}
	// determine size of text

	int cx = 0;
	int cy = 0;
	HFONT hFont = (HFONT) SendMessage( GetParent(hWnd), WM_GETFONT, 0, 0);
	HFONT hBoldFont = 0; 
	if (hFont)
	{	
		COLORREF color = RGB(192,0,0);//pSession->getPrintColor();
	
		if (color != RGB_COLOR_BLACK)
		{	SetTextColor( dc, color);
			SetBkColor( dc, RGB_COLOR_WHITE);
			LOGFONT logFont;
			GetObject( hFont, sizeof(LOGFONT), (LPSTR) &logFont);
			logFont.lfWeight = FW_BOLD;
			logFont.lfUnderline = TRUE;
			hBoldFont = CreateFontIndirect( &logFont);
			if (hBoldFont)
				hFont = hBoldFont;
		}

		//SelectObject( hDC, hFont);
		//DrawText( hDC, pText, -1, &Rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
		//if (hBoldFont)
		//	DeleteObject( hBoldFont);

	}
	SIZE size = {0,0};

	HFONT hOldFont = (HFONT) SelectObject( hDC, hFont);

	GetTextExtentExPoint(hDC, pText, _tcslen(pText), 999, NULL, NULL, &size); 

	// determine position of top-left corner of icon
	int x = Rect.left +(RectWidth(Rect) - size.cx)/2;//image_left (cx, Rect, style);
	int y = Rect.top + (RectHeight(Rect) - size.cy)/2;;//image_top (cy, Rect, style);
	style |= DST_PREFIXTEXT;
	HBRUSH hBr = (HBRUSH) GetStockObject(WHITE_BRUSH);
	HPEN hPen = (HPEN) GetStockObject(BLACK_PEN);
	int nMode = SetBkMode(hDC, TRANSPARENT);
	
	HBRUSH hOldBr = (HBRUSH)SelectObject(hDC, hBr); 
	HPEN hOldPen = (HPEN) SelectObject(hDC, hPen); 

	RECT r = {x,y,x+size.cx,y+size.cy+2};
	//FillRect(hDC, &r, hBr);
	Rectangle(hDC, x,y-1,x+size.cx,y+size.cy+2);
	DrawText( hDC, pText, -1, (LPRECT) &Rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	SetBkMode(hDC, nMode);
	SelectObject(hDC, hOldBr); 
	SelectObject(hDC, hOldPen); 
	SelectObject( hDC, hOldFont);

	if (hBoldFont)
		DeleteObject( hBoldFont);


	delete pText;
}

// calcultate the left position of the image so it is drawn on left, right or centred (the default)
// as dictated by the style settings.
static int image_left (int cx, const RECT& Rect, DWORD style)
{
	int x = Rect.left;
	if (cx > RectWidth(Rect) )
		cx = RectWidth(Rect);
	else if ((style & BS_CENTER) == BS_LEFT)
		x = Rect.left;
	else if ((style & BS_CENTER) == BS_RIGHT)
		x = Rect.right - cx;
	else
		x = Rect.left + (RectWidth(Rect) - cx)/2;
	return (x);
}

// calcultate the top position of the image so it is drawn on top, bottom or vertically centred (the default)
// as dictated by the style settings.
static int image_top (int cy, const RECT& Rect, DWORD style)
{
	int y = Rect.top;
	if (cy > RectHeight(Rect))
		cy = RectHeight(Rect);
	if ((style & BS_VCENTER) == BS_TOP)
		y = Rect.top;
	else if ((style & BS_VCENTER) == BS_BOTTOM)
		y = Rect.bottom - cy;
	else
		y = Rect.top + (RectHeight(Rect) - cy)/2;
	return (y);
}
*/

#endif //if 0 & we want to draw fancy icon buttons