www.pudn.com > XRayImg.rar > PPDrawManager.cpp


#include "stdafx.h" 
#include "PPDrawManager.h" 
 
/* 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
*/ 
 
/* 
	DIBs use RGBQUAD format: 
		0xbb 0xgg 0xrr 0x00 
*/ 
#ifndef CLR_TO_RGBQUAD 
#define CLR_TO_RGBQUAD(clr)     (RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr))) 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CPPDrawManager::CPPDrawManager() 
{ 
 
} 
 
CPPDrawManager::~CPPDrawManager() 
{ 
 
} 
 
void CPPDrawManager::GetSizeOfIcon(HICON hIcon, LPSIZE pSize) const 
{ 
	pSize->cx = 0; 
	pSize->cy = 0; 
	if (hIcon != NULL) 
	{ 
		ICONINFO ii; 
		// Gets icon dimension 
		::ZeroMemory(&ii, sizeof(ICONINFO)); 
		if (::GetIconInfo(hIcon, &ii)) 
		{ 
			pSize->cx = (DWORD)(ii.xHotspot * 2); 
			pSize->cy = (DWORD)(ii.yHotspot * 2); 
			//release icon mask bitmaps 
			if(ii.hbmMask) 
				::DeleteObject(ii.hbmMask); 
			if(ii.hbmColor) 
				::DeleteObject(ii.hbmColor); 
		} //if 
	} //if 
} //End GetSizeOfIcon 
 
void CPPDrawManager::GetSizeOfBitmap(HBITMAP hBitmap, LPSIZE pSize) const 
{ 
	pSize->cx = 0; 
	pSize->cy = 0; 
	if (hBitmap != NULL) 
	{ 
		BITMAP	csBitmapSize; 
		// Get bitmap size 
		int nRetValue = ::GetObject(hBitmap, sizeof(csBitmapSize), &csBitmapSize); 
		if (nRetValue) 
		{ 
			pSize->cx = (DWORD)csBitmapSize.bmWidth; 
			pSize->cy = (DWORD)csBitmapSize.bmHeight; 
		} //if 
	} //if 
} //End GetSizeOfBitmap 
 
void CPPDrawManager::AlphaBitBlt(HDC hDestDC, int nDestX, int nDestY, DWORD dwWidth, DWORD dwHeight, HDC hSrcDC, int nSrcX, int nSrcY, int percent /* = 100 */) 
{ 
	_ASSERT ((NULL != hDestDC) || (NULL != hSrcDC)); 
 
	if (percent >= 100) 
	{ 
		::BitBlt(hDestDC, nDestX, nDestY, dwWidth, dwHeight, hSrcDC, nSrcX, nSrcY, SRCCOPY); 
		return; 
	} //if 
 
	HDC hTempDC = ::CreateCompatibleDC(hDestDC); 
	if (NULL == hTempDC) 
		return; 
	 
	//Creates Source DIB 
	LPBITMAPINFO lpbiSrc; 
	// Fill in the BITMAPINFOHEADER 
	lpbiSrc = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)]; 
	lpbiSrc->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	lpbiSrc->bmiHeader.biWidth = dwWidth; 
	lpbiSrc->bmiHeader.biHeight = dwHeight; 
	lpbiSrc->bmiHeader.biPlanes = 1; 
	lpbiSrc->bmiHeader.biBitCount = 32; 
	lpbiSrc->bmiHeader.biCompression = BI_RGB; 
	lpbiSrc->bmiHeader.biSizeImage = dwWidth * dwHeight; 
	lpbiSrc->bmiHeader.biXPelsPerMeter = 0; 
	lpbiSrc->bmiHeader.biYPelsPerMeter = 0; 
	lpbiSrc->bmiHeader.biClrUsed = 0; 
	lpbiSrc->bmiHeader.biClrImportant = 0; 
	 
	COLORREF* pSrcBits = NULL; 
	HBITMAP hSrcDib = CreateDIBSection ( 
		hSrcDC, lpbiSrc, DIB_RGB_COLORS, (void **)&pSrcBits, 
		NULL, NULL); 
	 
	if ((NULL != hSrcDib) && (NULL != pSrcBits)) 
	{ 
		HBITMAP hOldTempBmp = (HBITMAP)::SelectObject (hTempDC, hSrcDib); 
		::BitBlt (hTempDC, 0, 0, dwWidth, dwHeight, hSrcDC, nSrcX, nSrcY, SRCCOPY); 
		::SelectObject (hTempDC, hOldTempBmp); 
		 
		//Creates Destination DIB 
		LPBITMAPINFO lpbiDest; 
		// Fill in the BITMAPINFOHEADER 
		lpbiDest = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)]; 
		lpbiDest->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
		lpbiDest->bmiHeader.biWidth = dwWidth; 
		lpbiDest->bmiHeader.biHeight = dwHeight; 
		lpbiDest->bmiHeader.biPlanes = 1; 
		lpbiDest->bmiHeader.biBitCount = 32; 
		lpbiDest->bmiHeader.biCompression = BI_RGB; 
		lpbiDest->bmiHeader.biSizeImage = dwWidth * dwHeight; 
		lpbiDest->bmiHeader.biXPelsPerMeter = 0; 
		lpbiDest->bmiHeader.biYPelsPerMeter = 0; 
		lpbiDest->bmiHeader.biClrUsed = 0; 
		lpbiDest->bmiHeader.biClrImportant = 0; 
		 
		COLORREF* pDestBits = NULL; 
		HBITMAP hDestDib = CreateDIBSection ( 
			hDestDC, lpbiDest, DIB_RGB_COLORS, (void **)&pDestBits, 
			NULL, NULL); 
		 
		if ((NULL != hDestDib) && (NULL != pDestBits)) 
		{ 
			::SelectObject (hTempDC, hDestDib); 
			::BitBlt (hTempDC, 0, 0, dwWidth, dwHeight, hDestDC, nDestX, nDestY, SRCCOPY); 
			::SelectObject (hTempDC, hOldTempBmp); 
 
			double src_darken = (double)percent / 100.0; 
			double dest_darken = 1.0 - src_darken; 
			 
			for (DWORD pixel = 0; pixel < dwWidth * dwHeight; pixel++, pSrcBits++, pDestBits++) 
			{ 
				*pDestBits = PixelAlpha(*pSrcBits, src_darken, *pDestBits, dest_darken); 
			} //for 
			 
			::SelectObject (hTempDC, hDestDib); 
			::BitBlt (hDestDC, nDestX, nDestY, dwWidth, dwHeight, hTempDC, 0, 0, SRCCOPY); 
			::SelectObject (hTempDC, hOldTempBmp); 
 
			delete lpbiDest; 
			::DeleteObject(hDestDib); 
		} //if 
		delete lpbiSrc; 
		::DeleteObject(hSrcDib); 
	} //if 
 
	::DeleteDC(hTempDC); 
} //End AlphaBitBlt 
 
void CPPDrawManager::AlphaChannelBitBlt(HDC hDestDC, int nDestX, int nDestY, DWORD dwWidth, DWORD dwHeight, HDC hSrcDC, int nSrcX, int nSrcY) 
{ 
	_ASSERT ((NULL != hDestDC) || (NULL != hSrcDC)); 
 
	HDC hTempDC = ::CreateCompatibleDC(hDestDC); 
	if (NULL == hTempDC) 
		return; 
	 
	//Creates Source DIB 
	LPBITMAPINFO lpbiSrc; 
	// Fill in the BITMAPINFOHEADER 
	lpbiSrc = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)]; 
	lpbiSrc->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	lpbiSrc->bmiHeader.biWidth = dwWidth; 
	lpbiSrc->bmiHeader.biHeight = dwHeight; 
	lpbiSrc->bmiHeader.biPlanes = 1; 
	lpbiSrc->bmiHeader.biBitCount = 32; 
	lpbiSrc->bmiHeader.biCompression = BI_RGB; 
	lpbiSrc->bmiHeader.biSizeImage = dwWidth * dwHeight; 
	lpbiSrc->bmiHeader.biXPelsPerMeter = 0; 
	lpbiSrc->bmiHeader.biYPelsPerMeter = 0; 
	lpbiSrc->bmiHeader.biClrUsed = 0; 
	lpbiSrc->bmiHeader.biClrImportant = 0; 
	 
	COLORREF* pSrcBits = NULL; 
	HBITMAP hSrcDib = CreateDIBSection ( 
		hSrcDC, lpbiSrc, DIB_RGB_COLORS, (void **)&pSrcBits, 
		NULL, NULL); 
	 
	if ((NULL != hSrcDib) && (NULL != pSrcBits)) 
	{ 
		HBITMAP hOldTempBmp = (HBITMAP)::SelectObject (hTempDC, hSrcDib); 
		::BitBlt (hTempDC, 0, 0, dwWidth, dwHeight, hSrcDC, nSrcX, nSrcY, SRCCOPY); 
		::SelectObject (hTempDC, hOldTempBmp); 
		 
		//Creates Destination DIB 
		LPBITMAPINFO lpbiDest; 
		// Fill in the BITMAPINFOHEADER 
		lpbiDest = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)]; 
		lpbiDest->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
		lpbiDest->bmiHeader.biWidth = dwWidth; 
		lpbiDest->bmiHeader.biHeight = dwHeight; 
		lpbiDest->bmiHeader.biPlanes = 1; 
		lpbiDest->bmiHeader.biBitCount = 32; 
		lpbiDest->bmiHeader.biCompression = BI_RGB; 
		lpbiDest->bmiHeader.biSizeImage = dwWidth * dwHeight; 
		lpbiDest->bmiHeader.biXPelsPerMeter = 0; 
		lpbiDest->bmiHeader.biYPelsPerMeter = 0; 
		lpbiDest->bmiHeader.biClrUsed = 0; 
		lpbiDest->bmiHeader.biClrImportant = 0; 
		 
		COLORREF* pDestBits = NULL; 
		HBITMAP hDestDib = CreateDIBSection ( 
			hDestDC, lpbiDest, DIB_RGB_COLORS, (void **)&pDestBits, 
			NULL, NULL); 
		 
		if ((NULL != hDestDib) && (NULL != pDestBits)) 
		{ 
			::SelectObject (hTempDC, hDestDib); 
			::BitBlt (hTempDC, 0, 0, dwWidth, dwHeight, hDestDC, nDestX, nDestY, SRCCOPY); 
			::SelectObject (hTempDC, hOldTempBmp); 
 
			double src_darken; 
			BYTE nAlpha; 
			 
			for (DWORD pixel = 0; pixel < dwWidth * dwHeight; pixel++, pSrcBits++, pDestBits++) 
			{ 
				nAlpha = LOBYTE(*pSrcBits >> 24); 
				src_darken = (double)nAlpha / 255.0; 
				*pDestBits = PixelAlpha(*pSrcBits, src_darken, *pDestBits, 1.0 - src_darken); 
			} //for 
			 
			::SelectObject (hTempDC, hDestDib); 
			::BitBlt (hDestDC, nDestX, nDestY, dwWidth, dwHeight, hTempDC, 0, 0, SRCCOPY); 
			::SelectObject (hTempDC, hOldTempBmp); 
 
			delete lpbiDest; 
			::DeleteObject(hDestDib); 
		} //if 
		delete lpbiSrc; 
		::DeleteObject(hSrcDib); 
	} //if 
 
	::DeleteDC(hTempDC); 
} //End of AlphaChannelBitBlt 
 
HBITMAP CPPDrawManager::CreateImageEffect(HBITMAP hBitmap, DWORD dwWidth, DWORD dwHeight, DWORD dwEffect, BOOL bUseMask /* = TRUE */, COLORREF clrMask /* = RGB(255, 0, 255) */, COLORREF clrMono /* = RGB(255, 255, 255) */) 
{ 
	HBITMAP hOldSrcBmp = NULL; 
	HBITMAP hOldResBmp = NULL;   
	HDC hMainDC = NULL; 
	HDC hSrcDC = NULL; 
	HDC hResDC = NULL; 
	 
	hMainDC = ::GetDC(NULL); 
	hSrcDC = ::CreateCompatibleDC(hMainDC); 
	hResDC = ::CreateCompatibleDC(hMainDC); 
 
	hOldSrcBmp = (HBITMAP)::SelectObject(hSrcDC, hBitmap); 
 
	LPBITMAPINFO lpbi; 
 
	// Fill in the BITMAPINFOHEADER 
	lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)]; 
	lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	lpbi->bmiHeader.biWidth = dwWidth; 
	lpbi->bmiHeader.biHeight = dwHeight; 
	lpbi->bmiHeader.biPlanes = 1; 
	lpbi->bmiHeader.biBitCount = 32; 
	lpbi->bmiHeader.biCompression = BI_RGB; 
	lpbi->bmiHeader.biSizeImage = dwWidth * dwHeight; 
	lpbi->bmiHeader.biXPelsPerMeter = 0; 
	lpbi->bmiHeader.biYPelsPerMeter = 0; 
	lpbi->bmiHeader.biClrUsed = 0; 
	lpbi->bmiHeader.biClrImportant = 0; 
 
	COLORREF* pBits = NULL; 
	HBITMAP hDibBmp = CreateDIBSection ( 
		hSrcDC, lpbi, DIB_RGB_COLORS, (void **)&pBits, 
		NULL, NULL); 
 
	if (hDibBmp == NULL || pBits == NULL) 
	{ 
		delete lpbi; 
		_ASSERT (FALSE); 
		return NULL; 
	} //if 
 
	hOldResBmp = (HBITMAP)::SelectObject (hResDC, hDibBmp); 
	::BitBlt (hResDC, 0, 0, dwWidth, dwHeight, hSrcDC, 0, 0, SRCCOPY); 
 
	clrMask = CLR_TO_RGBQUAD(clrMask); 
	clrMono = CLR_TO_RGBQUAD(clrMono); 
 
	DWORD dwAlpha; 
	for (DWORD pixel = 0; pixel < dwWidth * dwHeight; pixel++, *pBits++) 
	{ 
		COLORREF color = (COLORREF)*pBits; 
		//ENG: Extract an original alpha value 
		dwAlpha = color & 0xFF000000; 
		if (dwAlpha != 0)  
			m_bIsAlpha = TRUE; 
		if (bUseMask && (color == clrMask)) 
		{ 
			//This is transparent area 
			color = RGB(0, 0, 0); 
		} 
		else  
		{ 
			//ENG: Color conversion 
			if (dwEffect & IMAGE_EFFECT_GRAYEN) color = GrayMirrorColor(color); 
			if (dwEffect & IMAGE_EFFECT_DARKEN) color = DarkenColor(color, 0.75); 
			if (dwEffect & IMAGE_EFFECT_LIGHTEN) color = LightenColor(color, 0.25); 
			if (dwEffect & IMAGE_EFFECT_MONOCHROME) color = clrMono; 
		} //if 
		if (dwEffect & IMAGE_EFFECT_INVERT) color = InvertColor(color); 
		//ENG: Merges a color with an original alpha value 
		*pBits = (color | dwAlpha); 
	} //for 
 
	::SelectObject(hSrcDC, hOldSrcBmp); 
	::SelectObject(hResDC, hOldResBmp); 
	::DeleteDC(hSrcDC); 
	::DeleteDC(hResDC); 
	::ReleaseDC(NULL, hMainDC); 
	 
	delete lpbi; 
 
	return hDibBmp; 
} //End CreateImageEffect 
 
//---------------------------------------------------------- 
// CPPDrawManager::GrayMirrorColor() 
//	Graying color in RGBQUAD format 
//---------------------------------------------------------- 
// Parameter: 
//	clrColor	- RGBQUAD value from DIB 
// Return value: 
//	A grayed color in the RGBQUAD format 
//---------------------------------------------------------- 
COLORREF CPPDrawManager::GrayMirrorColor(COLORREF clrColor) 
{ 
	BYTE nGrayColor = (BYTE)((GetBValue(clrColor) * 0.299) + (GetGValue(clrColor) * 0.587) + (GetRValue(clrColor) * 0.114)); 
	 
	return RGB(nGrayColor, nGrayColor, nGrayColor); 
} //End of GrayMirrorColor 
 
COLORREF CPPDrawManager::GrayColor(COLORREF clrColor) 
{ 
	BYTE nGrayColor = (BYTE)((GetRValue(clrColor) * 0.299) + (GetGValue(clrColor) * 0.587) + (GetBValue(clrColor) * 0.114)); 
	 
	return RGB(nGrayColor, nGrayColor, nGrayColor); 
} //End GrayColor 
 
COLORREF CPPDrawManager::InvertColor(COLORREF clrColor) 
{ 
	return RGB(255 - GetRValue(clrColor), 255 - GetGValue(clrColor), 255 - GetBValue(clrColor)); 
} //End InvertColor 
 
COLORREF CPPDrawManager::DarkenColor(COLORREF clrColor, double darken) 
{ 
	if (darken >= 0.0 && darken < 1.0) 
	{ 
		BYTE color_r, color_g, color_b; 
		color_r = (BYTE)(GetRValue(clrColor) * darken); 
		color_g = (BYTE)(GetGValue(clrColor) * darken); 
		color_b = (BYTE)(GetBValue(clrColor) * darken); 
		clrColor = RGB(color_r, color_g, color_b); 
	} //if 
	 
	return clrColor; 
} //End DarkenColor 
 
COLORREF CPPDrawManager::LightenColor(COLORREF clrColor, double lighten) 
{ 
	if (lighten > 0.0 && lighten <= 1.0) 
	{ 
		BYTE color_r, color_g, color_b; 
		 
		lighten += 1.0; 
		color_r = (BYTE)min((DWORD)GetRValue(clrColor) * lighten, 255.0); 
		color_g = (BYTE)min((DWORD)GetGValue(clrColor) * lighten, 255.0); 
		color_b = (BYTE)min((DWORD)GetBValue(clrColor) * lighten, 255.0); 
		clrColor = RGB(color_r, color_g, color_b); 
/*		 
		lighten *= 255 
		color_r = (BYTE)max(0, min(255, (int)((color_r - 128) * 2.0 + 128 + lighten))); 
		color_g = (BYTE)max(0, min(255, (int)((color_g - 128) * 2.0 + 128 + lighten))); 
		color_b = (BYTE)max(0, min(255, (int)((color_b - 128) * 2.0 + 128 + lighten))); 
		clrColor = RGB(color_r, color_g, color_b); 
*/ 
	} //if 
	 
	return clrColor; 
} //End LightenColor 
 
COLORREF CPPDrawManager::PixelAlpha(COLORREF clrSrc, double src_darken, COLORREF clrDest, double dest_darken) 
{ 
	return RGB (GetRValue (clrSrc) * src_darken + GetRValue (clrDest) * dest_darken,  
				GetGValue (clrSrc) * src_darken + GetGValue (clrDest) * dest_darken,  
				GetBValue (clrSrc) * src_darken + GetBValue (clrDest) * dest_darken); 
	 
} //End PixelAlpha 
 
HICON CPPDrawManager::StretchIcon(HICON hIcon, DWORD dwWidth, DWORD dwHeight) 
{ 
	HICON hStretchedIcon = NULL; 
	HDC   hMainDC = NULL; 
	HDC   hSrcDC = NULL; 
	HDC   hDestDC = NULL; 
	BITMAP bmp; 
	HBITMAP hOldSrcBitmap = NULL; 
	HBITMAP hOldDestBitmap = NULL; 
	ICONINFO csOriginal, csStretched; 
	 
	if (!::GetIconInfo(hIcon, &csOriginal)) 
		return FALSE; 
	 
	hMainDC = ::GetDC(NULL); 
	hSrcDC = ::CreateCompatibleDC(hMainDC); 
	hDestDC = ::CreateCompatibleDC(hMainDC); 
	 
	if ((NULL == hMainDC) || (NULL == hSrcDC) || (NULL == hDestDC)) 
		return NULL; 
	 
	if (::GetObject(csOriginal.hbmColor, sizeof(BITMAP), &bmp)) 
	{ 
		DWORD	dwWidthOrg = csOriginal.xHotspot * 2; 
		DWORD	dwHeightOrg = csOriginal.yHotspot * 2; 
		 
		csStretched.hbmColor = ::CreateBitmap(dwWidth, dwHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL); 
		if (NULL != csStretched.hbmColor) 
		{ 
			hOldSrcBitmap = (HBITMAP)::SelectObject(hSrcDC, csOriginal.hbmColor); 
			hOldDestBitmap = (HBITMAP)::SelectObject(hDestDC, csStretched.hbmColor); 
			::StretchBlt(hDestDC, 0, 0, dwWidth, dwHeight, hSrcDC, 0, 0, dwWidthOrg, dwHeightOrg, SRCCOPY); 
			if (::GetObject(csOriginal.hbmMask, sizeof(BITMAP), &bmp)) 
			{ 
				csStretched.hbmMask = ::CreateBitmap(dwWidth, dwHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL); 
				if (NULL != csStretched.hbmMask) 
				{ 
					::SelectObject(hSrcDC, csOriginal.hbmMask); 
					::SelectObject(hDestDC, csStretched.hbmMask); 
					::StretchBlt(hDestDC, 0, 0, dwWidth, dwHeight, hSrcDC, 0, 0, dwWidthOrg, dwHeightOrg, SRCCOPY); 
				} //if 
			} //if 
			::SelectObject(hSrcDC, hOldSrcBitmap); 
			::SelectObject(hDestDC, hOldDestBitmap); 
			csStretched.fIcon = TRUE; 
			hStretchedIcon = ::CreateIconIndirect(&csStretched); 
		} //if 
		::DeleteObject(csStretched.hbmColor); 
		::DeleteObject(csStretched.hbmMask); 
	} //if 
	 
	::DeleteObject(csOriginal.hbmColor); 
	::DeleteObject(csOriginal.hbmMask); 
	::DeleteDC(hSrcDC); 
	::DeleteDC(hDestDC); 
	::ReleaseDC(NULL, hMainDC); 
	 
	return hStretchedIcon; 
} //End StretchIcon 
 
void CPPDrawManager::FillGradient (HDC hDC, LPCRECT lpRect,  
								COLORREF colorStart, COLORREF colorFinish,  
								BOOL bHorz/* = TRUE*/) 
{ 
    // this will make 2^6 = 64 fountain steps 
    int nShift = 6; 
    int nSteps = 1 << nShift; 
 
	RECT r2; 
	r2.top = lpRect->top; 
	r2.left = lpRect->left; 
	r2.right = lpRect->right; 
	r2.bottom = lpRect->bottom; 
 
	int nHeight = lpRect->bottom - lpRect->top; 
	int nWidth = lpRect->right - lpRect->left; 
 
	for (int i = 0; i < nSteps; i++) 
    { 
        // do a little alpha blending 
        BYTE bR = (BYTE) ((GetRValue(colorStart) * (nSteps - i) + 
                   GetRValue(colorFinish) * i) >> nShift); 
        BYTE bG = (BYTE) ((GetGValue(colorStart) * (nSteps - i) + 
                   GetGValue(colorFinish) * i) >> nShift); 
        BYTE bB = (BYTE) ((GetBValue(colorStart) * (nSteps - i) + 
                   GetBValue(colorFinish) * i) >> nShift); 
 
		HBRUSH hBrush = ::CreateSolidBrush(RGB(bR, bG, bB)); 
		 
        // then paint with the resulting color 
 
        if (!bHorz) 
        { 
            r2.top = lpRect->top + ((i * nHeight) >> nShift); 
            r2.bottom = lpRect->top + (((i + 1) * nHeight) >> nShift); 
            if ((r2.bottom - r2.top) > 0) 
                ::FillRect(hDC, &r2, hBrush); 
        } 
        else 
        { 
            r2.left = lpRect->left + ((i * nWidth) >> nShift); 
            r2.right = lpRect->left + (((i + 1) * nWidth) >> nShift); 
            if ((r2.right - r2.left) > 0) 
                ::FillRect(hDC, &r2, hBrush); 
        } //if 
		 
		if (NULL != hBrush) 
		{ 
			::DeleteObject(hBrush); 
			hBrush = NULL; 
		} //if 
    } //for 
} //End FillGradient 
 
#ifdef USE_SHADE 
void CPPDrawManager::SetShade(LPCRECT lpRect, UINT shadeID /* = 0 */, BYTE granularity /* = 8 */,  
						  BYTE coloring /* = 0 */, COLORREF hicr /* = 0 */, COLORREF midcr /* = 0 */, COLORREF locr /* = 0 */) 
{ 
	long	sXSize,sYSize,bytes,j,i,k,h; 
	BYTE	*iDst ,*posDst; 
	 
	sYSize = lpRect->bottom - lpRect->top;  
	sXSize = lpRect->right - lpRect->left;  
 
	m_dNormal.Create(sXSize,sYSize,8);					//create the default bitmap 
 
	long r,g,b;											//build the shaded palette 
	for(i = 0; i < 129; i++) 
	{ 
		r=((128-i)*GetRValue(locr)+i*GetRValue(midcr))/128; 
		g=((128-i)*GetGValue(locr)+i*GetGValue(midcr))/128; 
		b=((128-i)*GetBValue(locr)+i*GetBValue(midcr))/128; 
		m_dNormal.SetPaletteIndex((BYTE)i,(BYTE)r,(BYTE)g,(BYTE)b); 
	} //for 
	for(i=1;i<129;i++){ 
		r=((128-i)*GetRValue(midcr)+i*GetRValue(hicr))/128; 
		g=((128-i)*GetGValue(midcr)+i*GetGValue(hicr))/128; 
		b=((128-i)*GetBValue(midcr)+i*GetBValue(hicr))/128; 
		m_dNormal.SetPaletteIndex((BYTE)(i+127),(BYTE)r,(BYTE)g,(BYTE)b); 
	} //for 
 
	m_dNormal.BlendPalette(hicr,coloring);	//color the palette 
 
	bytes = m_dNormal.GetLineWidth(); 
	iDst = m_dNormal.GetBits(); 
	posDst =iDst; 
	long a,x,y,d,xs,idxmax,idxmin; 
 
	int grainx2 = RAND_MAX/(max(1,2*granularity)); 
	idxmax=255-granularity; 
	idxmin=granularity; 
 
	switch (shadeID) 
	{ 
//---------------------------------------------------- 
	case EFFECT_METAL: 
		m_dNormal.Clear(); 
		// create the strokes 
		k=40;	//stroke granularity 
		for(a=0;a<200;a++){ 
			x=rand()/(RAND_MAX/sXSize); //stroke postion 
			y=rand()/(RAND_MAX/sYSize);	//stroke position 
			xs=rand()/(RAND_MAX/min(sXSize,sYSize))/2; //stroke lenght 
			d=rand()/(RAND_MAX/k);	//stroke color 
			for(i=0;i0)&&((y+i)0)) 
					m_dNormal.SetPixelIndex(sXSize-x+i,y-i,(BYTE)d); 
			} //for 
		} //for 
		//blend strokes with SHS_DIAGONAL 
		posDst =iDst; 
		a=(idxmax-idxmin-k)/2; 
		for(i = 0; i < sYSize; i++) { 
			for(j = 0; j < sXSize; j++) { 
				d=posDst[j]+((a*i)/sYSize+(a*(sXSize-j))/sXSize); 
				posDst[j]=(BYTE)d; 
				posDst[j]+=rand()/grainx2; 
			} //for 
			posDst+=bytes; 
		} //for 
 
		break; 
//---------------------------------------------------- 
	case EFFECT_HARDBUMP:	//  
		//set horizontal bump 
		for(i = 0; i < sYSize; i++) { 
			k=(255*i/sYSize)-127; 
			k=(k*(k*k)/128)/128; 
			k=(k*(128-granularity*2))/128+128; 
			for(j = 0; j < sXSize; j++) { 
				posDst[j]=(BYTE)k; 
				posDst[j]+=rand()/grainx2-granularity; 
			} //for 
			posDst+=bytes; 
		} //for 
		//set vertical bump 
		d=min(16,sXSize/6);	//max edge=16 
		a=sYSize*sYSize/4; 
		posDst =iDst; 
		for(i = 0; i < sYSize; i++) { 
			y=i-sYSize/2; 
			for(j = 0; j < sXSize; j++) { 
				x=j-sXSize/2; 
				xs=sXSize/2-d+(y*y*d)/a; 
				if (x>xs) posDst[j]=(BYTE)idxmin+(BYTE)(((sXSize-j)*128)/d); 
				if ((x+xs)<0) posDst[j]=(BYTE)idxmax-(BYTE)((j*128)/d); 
				posDst[j]+=rand()/grainx2-granularity; 
			} //for 
			posDst+=bytes; 
		} //for 
		break; 
//---------------------------------------------------- 
	case EFFECT_SOFTBUMP: // 
		for(i = 0; i < sYSize; i++) { 
			h=(255*i/sYSize)-127; 
			for(j = 0; j < sXSize; j++) { 
				k=(255*(sXSize-j)/sXSize)-127; 
				k=(h*(h*h)/128)/128+(k*(k*k)/128)/128; 
				k=k*(128-granularity)/128+128; 
				if (kidxmax) k=idxmax; 
				posDst[j]=(BYTE)k; 
				posDst[j]+=rand()/grainx2-granularity; 
			} //for 
			posDst+=bytes; 
		} //for 
		break; 
//---------------------------------------------------- 
	case EFFECT_VBUMP: //  
		for(j = 0; j < sXSize; j++) { 
			k=(255*(sXSize-j)/sXSize)-127; 
			k=(k*(k*k)/128)/128; 
			k=(k*(128-granularity))/128+128; 
			for(i = 0; i < sYSize; i++) { 
				posDst[j+i*bytes]=(BYTE)k; 
				posDst[j+i*bytes]+=rand()/grainx2-granularity; 
			} //for 
		} //for 
		break; 
//---------------------------------------------------- 
	case EFFECT_HBUMP: // 
		for(i = 0; i < sYSize; i++) { 
			k=(255*i/sYSize)-127; 
			k=(k*(k*k)/128)/128; 
			k=(k*(128-granularity))/128+128; 
			for(j = 0; j < sXSize; j++) { 
				posDst[j]=(BYTE)k; 
				posDst[j]+=rand()/grainx2-granularity; 
			} //for 
			posDst+=bytes; 
		} //for 
		break; 
//---------------------------------------------------- 
	case EFFECT_DIAGSHADE:	// 
		a=(idxmax-idxmin)/2; 
		for(i = 0; i < sYSize; i++) { 
			for(j = 0; j < sXSize; j++) { 
				posDst[j]=(BYTE)(idxmin+a*i/sYSize+a*(sXSize-j)/sXSize); 
				posDst[j]+=rand()/grainx2-granularity; 
			} //for 
			posDst+=bytes; 
		} //for 
		break; 
//---------------------------------------------------- 
	case EFFECT_HSHADE:	// 
		a=idxmax-idxmin; 
		for(i = 0; i < sYSize; i++) { 
			k=a*i/sYSize+idxmin; 
			for(j = 0; j < sXSize; j++) { 
				posDst[j]=(BYTE)k; 
				posDst[j]+=rand()/grainx2-granularity; 
			} //for 
			posDst+=bytes; 
		} //for 
		break; 
//---------------------------------------------------- 
	case EFFECT_VSHADE:	//: 
		a=idxmax-idxmin; 
		for(j = 0; j < sXSize; j++) { 
			k=a*(sXSize-j)/sXSize+idxmin; 
			for(i = 0; i < sYSize; i++) { 
				posDst[j+i*bytes]=(BYTE)k; 
				posDst[j+i*bytes]+=rand()/grainx2-granularity; 
			} //for 
		} //for 
		break; 
//---------------------------------------------------- 
	case EFFECT_NOISE: 
		for(i = 0; i < sYSize; i++) { 
			for(j = 0; j < sXSize; j++) { 
				posDst[j]=128+rand()/grainx2-granularity; 
			} //for 
			posDst+=bytes; 
		} //for 
	} //switch 
//---------------------------------------------------- 
} //End SetShade 
#endif 
 
void CPPDrawManager::FillEffect(HDC hDC, DWORD dwEffect, LPCRECT lpRect, COLORREF clrBegin, COLORREF clrMid /* = 0 */, COLORREF clrEnd /* = 0 */,  BYTE granularity /* = 0 */, BYTE coloring /* = 0 */) 
{ 
	HBRUSH hBrush = NULL; 
 
	RECT rect; 
	rect.left = lpRect->left; 
	rect.top = lpRect->top; 
	rect.right = lpRect->right; 
	rect.bottom = lpRect->bottom; 
 
	int nHeight = rect.bottom - rect.top; 
	int nWidth = rect.right - rect.left; 
	 
	switch (dwEffect) 
	{ 
	default: 
		hBrush = ::CreateSolidBrush(clrBegin); 
		::FillRect(hDC, lpRect, hBrush); 
		break; 
	case EFFECT_HGRADIENT: 
		FillGradient(hDC, lpRect, clrBegin, clrEnd, TRUE); 
		break; 
	case EFFECT_VGRADIENT: 
		FillGradient(hDC, lpRect, clrBegin, clrEnd, FALSE); 
		break; 
	case EFFECT_HCGRADIENT: 
		rect.right = rect.left + nWidth / 2; 
		FillGradient(hDC, &rect, clrBegin, clrEnd, TRUE); 
		rect.left = rect.right; 
		rect.right = lpRect->right; 
		FillGradient(hDC, &rect, clrEnd, clrBegin, TRUE); 
		break; 
	case EFFECT_3HGRADIENT: 
		rect.right = rect.left + nWidth / 2; 
		FillGradient(hDC, &rect, clrBegin, clrMid, TRUE); 
		rect.left = rect.right; 
		rect.right = lpRect->right; 
		FillGradient(hDC, &rect, clrMid, clrEnd, TRUE); 
		break; 
	case EFFECT_VCGRADIENT: 
		rect.bottom = rect.top + nHeight / 2; 
		FillGradient(hDC, &rect, clrBegin, clrEnd, FALSE); 
		rect.top = rect.bottom; 
		rect.bottom = lpRect->bottom; 
		FillGradient(hDC, &rect, clrEnd, clrBegin, FALSE); 
		break; 
	case EFFECT_3VGRADIENT: 
		rect.bottom = rect.top + nHeight / 2; 
		FillGradient(hDC, &rect, clrBegin, clrMid, FALSE); 
		rect.top = rect.bottom; 
		rect.bottom = lpRect->bottom; 
		FillGradient(hDC, &rect, clrMid, clrEnd, FALSE); 
		break; 
#ifdef USE_SHADE 
	case EFFECT_NOISE: 
	case EFFECT_DIAGSHADE: 
	case EFFECT_HSHADE: 
	case EFFECT_VSHADE: 
	case EFFECT_HBUMP: 
	case EFFECT_VBUMP: 
	case EFFECT_SOFTBUMP: 
	case EFFECT_HARDBUMP: 
	case EFFECT_METAL: 
		rect.left = 0; 
		rect.top = 0; 
		rect.right = nWidth; 
		rect.bottom = nHeight; 
		SetShade(&rect, dwEffect, granularity, coloring, clrBegin, clrMid, clrEnd); 
		m_dNormal.Draw(hDC, lpRect->left, lpRect->top); 
		break;  
#endif 
	} //switch 
 
	if (NULL != hBrush) 
	{ 
		::DeleteObject(hBrush); 
		hBrush = NULL; 
	} //if 
} //End FillEffect 
 
void CPPDrawManager::MultipleCopy(HDC hDestDC, int nDestX, int nDestY, DWORD dwDestWidth, DWORD dwDestHeight,  
										HDC hSrcDC, int nSrcX, int nSrcY, DWORD dwSrcWidth, DWORD dwSrcHeight) 
{ 
	// Horizontal copying 
	int right, bottom; 
	int nDestRight = (int)(nDestX + dwDestWidth); 
	int nDestBottom = (int)(nDestY + dwDestHeight); 
	for (int x = nDestX; x < nDestRight; x+= dwSrcWidth) 
	{ 
		right = min (x + (int)dwSrcWidth, nDestRight); 
		// Vertical copying 
		for (int y = nDestY; y < nDestBottom; y+= dwSrcHeight) 
		{ 
			bottom = min (y + (int)dwSrcHeight, nDestBottom); 
			::BitBlt(hDestDC, x, y, right - x, bottom - y, hSrcDC, nSrcX, nSrcY, SRCCOPY); 
		} //for 
	} //for 
} //End MultipleCopy 
 
void CPPDrawManager::DrawBitmap(HDC hDC, int x, int y, DWORD dwWidth, DWORD dwHeight, HBITMAP hSrcBitmap, 
					BOOL bUseMask, COLORREF crMask,  
					DWORD dwEffect /* = IMAGE_EFFECT_NONE */,  
					BOOL bShadow /* = FALSE */,  
					DWORD dwCxShadow /* = PPDRAWMANAGER_SHADOW_XOFFSET */,  
					DWORD dwCyShadow /* = PPDRAWMANAGER_SHADOW_YOFFSET */, 
					DWORD dwCxDepth /* = PPDRAWMANAGER_SHADOW_XDEPTH */,  
					DWORD dwCyDepth /* = PPDRAWMANAGER_SHADOW_YDEPTH */, 
					COLORREF clrShadow /* = PPDRAWMANAGER_SHADOW_COLOR */) 
{ 
	m_bIsAlpha = FALSE; 
	if (NULL == hSrcBitmap) 
		return; 
 
	SIZE sz; 
	GetSizeOfBitmap(hSrcBitmap, &sz); 
 
	HDC hSrcDC = ::CreateCompatibleDC(hDC); 
	HDC hDestDC = ::CreateCompatibleDC(hDC); 
	 
	HBITMAP hBitmapTemp = ::CreateCompatibleBitmap(hDC, dwWidth, dwHeight); 
 
	HBITMAP hOldSrcBitmap = (HBITMAP)::SelectObject(hSrcDC, hSrcBitmap); 
	HBITMAP hOldDestBitmap = (HBITMAP)::SelectObject(hDestDC, hBitmapTemp); 
 
	//Scales a bitmap if need 
	if (((DWORD)sz.cx != dwWidth) || ((DWORD)sz.cy != dwHeight)) 
		::StretchBlt(hDestDC, 0, 0, dwWidth, dwHeight, hSrcDC, 0, 0, sz.cx, sz.cy, SRCCOPY); 
	else 
		::BitBlt(hDestDC, 0, 0, dwWidth, dwHeight, hSrcDC, 0, 0, SRCCOPY); 
 
	::SelectObject(hDestDC, hOldDestBitmap); 
	 
	HBITMAP hMaskBmp = CreateImageEffect(hBitmapTemp, dwWidth, dwHeight, IMAGE_EFFECT_MASK, bUseMask, crMask); 
	HBITMAP hBitmap = CreateImageEffect(hBitmapTemp, dwWidth, dwHeight, dwEffect, bUseMask, crMask, clrShadow); 
	 
	if (bShadow) 
	{ 
		if (dwEffect & IMAGE_EFFECT_SHADOW) 
		{ 
			POINT ptShadow; 
			ptShadow.x = x + dwCxShadow; 
			ptShadow.y = y + dwCyShadow; 
			HBITMAP hShadowBmp =  CreateImageEffect(hBitmapTemp, dwWidth, dwHeight, IMAGE_EFFECT_MASK, bUseMask, crMask, InvertColor(clrShadow)); 
			DrawShadow(hDC, ptShadow.x, ptShadow.y, dwWidth, dwHeight, hShadowBmp, dwEffect & IMAGE_EFFECT_GRADIENT_SHADOW, dwCxDepth, dwCyDepth); 
			::DeleteObject(hShadowBmp); 
		} 
		else 
		{ 
			x += dwCxShadow; 
			y += dwCyShadow; 
		} //if 
	} //if 
	 
	if (m_bIsAlpha) 
	{ 
		::SelectObject(hSrcDC, hBitmap); 
		AlphaChannelBitBlt(hDC, x, y, dwWidth, dwHeight, hSrcDC, 0, 0); 
	} 
	else 
	{ 
		//Merge the image mask with background 
		::SelectObject(hSrcDC, hMaskBmp); 
		::BitBlt(hDC, x, y, dwWidth, dwHeight, hSrcDC, 0, 0, SRCAND); 
		 
		//Draw the image 
		::SelectObject(hSrcDC, hBitmap); 
		::BitBlt(hDC, x, y, dwWidth, dwHeight, hSrcDC, 0, 0, SRCPAINT); 
	} 
	 
	::SelectObject(hSrcDC, hOldSrcBitmap); 
	 
	::DeleteDC(hDestDC); 
	::DeleteDC(hSrcDC); 
 
	::DeleteObject(hBitmap); 
	::DeleteObject(hMaskBmp); 
	::DeleteObject(hBitmapTemp); 
} //End DrawBitmap 
 
void CPPDrawManager::DrawIcon(HDC hDC, int x, int y, DWORD dwWidth, DWORD dwHeight, HICON hSrcIcon, 
  							DWORD dwEffect /* = IMAGE_EFFECT_NONE */,  
							BOOL bShadow /* = FALSE */,  
							DWORD dwCxShadow /* = PPDRAWMANAGER_SHADOW_XOFFSET */,  
							DWORD dwCyShadow /* = PPDRAWMANAGER_SHADOW_YOFFSET */, 
							DWORD dwCxDepth /* = PPDRAWMANAGER_SHADOW_XDEPTH */,  
							DWORD dwCyDepth /* = PPDRAWMANAGER_SHADOW_YDEPTH */, 
							COLORREF clrShadow /* = PPDRAWMANAGER_SHADOW_COLOR */) 
{ 
	m_bIsAlpha = FALSE; 
	if (NULL == hSrcIcon) 
		return; 
 
	SIZE sz; 
	GetSizeOfIcon(hSrcIcon, &sz); 
 
	HICON hIcon = NULL; 
 
	if (((DWORD)sz.cx == dwWidth) && ((DWORD)sz.cy == dwHeight)) 
		hIcon = ::CopyIcon(hSrcIcon); 
	else hIcon = StretchIcon(hSrcIcon, dwWidth, dwHeight); 
	 
	ICONINFO csOriginal; 
 
	if (!::GetIconInfo(hIcon, &csOriginal)) 
		return; 
 
	HDC hSrcDC = ::CreateCompatibleDC(hDC); 
	 
	HBITMAP hBitmap; 
	if (dwEffect & IMAGE_EFFECT_MONOCHROME) 
		hBitmap = CreateImageEffect(csOriginal.hbmMask, dwWidth, dwHeight, dwEffect, TRUE, RGB(255, 255, 255), clrShadow); 
	else 
		hBitmap = CreateImageEffect(csOriginal.hbmColor, dwWidth, dwHeight, dwEffect, TRUE, RGB(0, 0, 0), clrShadow); 
	HBITMAP hOldSrcBitmap = (HBITMAP)::SelectObject(hSrcDC, hBitmap); 
 
	if (bShadow) 
	{ 
		if (dwEffect & IMAGE_EFFECT_SHADOW) 
		{ 
			POINT ptShadow; 
			ptShadow.x = x + dwCxShadow; 
			ptShadow.y = y + dwCyShadow; 
			HBITMAP hShadowBmp =  CreateImageEffect(csOriginal.hbmMask, dwWidth, dwHeight, IMAGE_EFFECT_MASK, TRUE, RGB(255, 255, 255), InvertColor(clrShadow)); 
			DrawShadow(hDC, ptShadow.x, ptShadow.y, dwWidth, dwHeight, hShadowBmp, dwEffect & IMAGE_EFFECT_GRADIENT_SHADOW, dwCxDepth, dwCyDepth); 
			::DeleteObject(hShadowBmp); 
		} 
		else 
		{ 
			x += dwCxShadow; 
			y += dwCyShadow; 
		} //if 
	} //if 
	 
	if (m_bIsAlpha) 
	{ 
//		::SelectObject(hSrcDC, hBitmap); 
		AlphaChannelBitBlt(hDC, x, y, dwWidth, dwHeight, hSrcDC, 0, 0); 
	} 
	else 
	{ 
		//------------------------------------------------------------------- 
		// !!! ATTENTION !!! 
		// I don't know why a icon uses text's color 
		// Therefore I change a text's color to BLACK and after draw I restore 
		// original color 
		//------------------------------------------------------------------- 
		COLORREF crOldColor = ::SetTextColor(hDC, RGB(0, 0, 0)); 
		//Merge the image mask with background 
		::SelectObject(hSrcDC, csOriginal.hbmMask); 
		::BitBlt(hDC, x, y, dwWidth, dwHeight, hSrcDC, 0, 0, SRCAND); 
		//Draw the image 
		::SelectObject(hSrcDC, hBitmap); 
		::BitBlt(hDC, x, y, dwWidth, dwHeight, hSrcDC, 0, 0, SRCPAINT); 
		::SetTextColor(hDC, crOldColor); 
	} //if 
 
	::SelectObject(hSrcDC, hOldSrcBitmap); 
	::DeleteDC(hSrcDC); 
	::DeleteObject(hBitmap); 
	::DestroyIcon(hIcon); 
 
	::DeleteObject(csOriginal.hbmColor); 
	::DeleteObject(csOriginal.hbmMask); 
} //End DrawIcon 
 
void CPPDrawManager::DrawShadow(HDC hDestDC, int nDestX, int nDestY, DWORD dwWidth, DWORD dwHeight, HBITMAP hMask, BOOL bGradient /* = FALSE */, DWORD dwDepthX /* = PPDRAWMANAGER_SHADOW_YOFFSET */, DWORD dwDepthY /* = PPDRAWMANAGER_SHADOW_XOFFSET */) 
{ 
	HDC hSrcDC = ::CreateCompatibleDC(hDestDC); 
	if (NULL == hSrcDC) 
		return; 
 
	HDC hTempDC = ::CreateCompatibleDC(hDestDC); 
	if (NULL == hTempDC) 
	{ 
		::DeleteDC(hSrcDC); 
		return; 
	} // if 
	 
	//Creates Source DIB 
	LPBITMAPINFO lpbiSrc; 
	// Fill in the BITMAPINFOHEADER 
	lpbiSrc = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)]; 
	lpbiSrc->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	lpbiSrc->bmiHeader.biWidth = dwWidth; 
	lpbiSrc->bmiHeader.biHeight = dwHeight; 
	lpbiSrc->bmiHeader.biPlanes = 1; 
	lpbiSrc->bmiHeader.biBitCount = 32; 
	lpbiSrc->bmiHeader.biCompression = BI_RGB; 
	lpbiSrc->bmiHeader.biSizeImage = dwWidth * dwHeight; 
	lpbiSrc->bmiHeader.biXPelsPerMeter = 0; 
	lpbiSrc->bmiHeader.biYPelsPerMeter = 0; 
	lpbiSrc->bmiHeader.biClrUsed = 0; 
	lpbiSrc->bmiHeader.biClrImportant = 0; 
	 
	COLORREF* pSrcBits = NULL; 
	HBITMAP hSrcDib = CreateDIBSection ( 
		hSrcDC, lpbiSrc, DIB_RGB_COLORS, (void **)&pSrcBits, 
		NULL, NULL); 
	 
	if ((NULL != hSrcDib) && (NULL != pSrcBits)) 
	{ 
		HBITMAP hOldSrcBmp = (HBITMAP)::SelectObject (hSrcDC, hSrcDib); 
		HBITMAP hOldTempBmp = (HBITMAP)::SelectObject (hTempDC, hMask); 
		if (bGradient) 
		{ 
			if (!(dwDepthX & 0x1)) dwDepthX++; 
			if (!(dwDepthY & 0x1)) dwDepthY++; 
			::BitBlt(hSrcDC, 0, 0, dwWidth, dwHeight, hTempDC, 0, 0, WHITENESS); 
			::StretchBlt (hSrcDC, dwDepthX / 2, dwDepthY / 2, dwWidth - dwDepthX, dwHeight - dwDepthY, hTempDC, 0, 0, dwWidth, dwHeight, SRCCOPY); 
		} 
		else 
		{ 
			::BitBlt(hSrcDC, 0, 0, dwWidth, dwHeight, hTempDC, 0, 0, SRCCOPY); 
		} //if 
		::SelectObject (hTempDC, hOldTempBmp); 
		::SelectObject (hSrcDC, hOldSrcBmp); 
		 
		//Creates Destination DIB 
		LPBITMAPINFO lpbiDest; 
		// Fill in the BITMAPINFOHEADER 
		lpbiDest = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)]; 
		lpbiDest->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
		lpbiDest->bmiHeader.biWidth = dwWidth; 
		lpbiDest->bmiHeader.biHeight = dwHeight; 
		lpbiDest->bmiHeader.biPlanes = 1; 
		lpbiDest->bmiHeader.biBitCount = 32; 
		lpbiDest->bmiHeader.biCompression = BI_RGB; 
		lpbiDest->bmiHeader.biSizeImage = dwWidth * dwHeight; 
		lpbiDest->bmiHeader.biXPelsPerMeter = 0; 
		lpbiDest->bmiHeader.biYPelsPerMeter = 0; 
		lpbiDest->bmiHeader.biClrUsed = 0; 
		lpbiDest->bmiHeader.biClrImportant = 0; 
		 
		COLORREF* pDestBits = NULL; 
		HBITMAP hDestDib = CreateDIBSection ( 
			hDestDC, lpbiDest, DIB_RGB_COLORS, (void **)&pDestBits, 
			NULL, NULL); 
		 
		if ((NULL != hDestDib) && (NULL != pDestBits)) 
		{ 
			::SelectObject (hTempDC, hDestDib); 
			::BitBlt (hTempDC, 0, 0, dwWidth, dwHeight, hDestDC, nDestX, nDestY, SRCCOPY); 
			::SelectObject (hTempDC, hOldTempBmp); 
			 
			if (bGradient) 
			{ 
				double * depth = new double [dwWidth * dwHeight]; 
				SmoothMaskImage(dwWidth, dwHeight, pSrcBits, dwDepthX, dwDepthY, depth); 
				for(DWORD pixel = 0; pixel < dwWidth * dwHeight; pixel++, pDestBits++) 
					*pDestBits = DarkenColor(*pDestBits, *(depth + pixel)); 
				delete [] depth; 
			} 
			else 
			{ 
				for(DWORD pixel = 0; pixel < dwWidth * dwHeight; pixel++, pSrcBits++, pDestBits++) 
					*pDestBits = DarkenColor(*pDestBits, (double)GetRValue(*pSrcBits) / 255.0); 
			} //if 
				 
			 
			::SelectObject (hTempDC, hDestDib); 
			::BitBlt (hDestDC, nDestX, nDestY, dwWidth, dwHeight, hTempDC, 0, 0, SRCCOPY); 
			::SelectObject (hTempDC, hOldTempBmp); 
 
			delete lpbiDest; 
			::DeleteObject(hDestDib); 
		} //if 
		delete lpbiSrc; 
		::DeleteObject(hSrcDib); 
	} //if 
	::DeleteDC(hTempDC); 
	::DeleteDC(hSrcDC); 
} //End DrawIcon 
 
void CPPDrawManager::DrawImageList(HDC hDC, int x, int y, DWORD dwWidth, DWORD dwHeight, HBITMAP hSrcBitmap, 
					int nIndex, int cx, int cy, 
					BOOL bUseMask, COLORREF crMask,  
					DWORD dwEffect /*= IMAGE_EFFECT_NONE*/,  
					BOOL bShadow /*= FALSE*/,  
					DWORD dwCxShadow /*= PPDRAWMANAGER_SHADOW_XOFFSET*/,  
					DWORD dwCyShadow /*= PPDRAWMANAGER_SHADOW_YOFFSET*/, 
					DWORD dwCxDepth /*= PPDRAWMANAGER_SHADOW_XDEPTH*/,  
					DWORD dwCyDepth /*= PPDRAWMANAGER_SHADOW_YDEPTH*/, 
					COLORREF clrShadow /*= PPDRAWMANAGER_SHADOW_COLOR*/) 
{ 
	if ((NULL == hSrcBitmap) || !cx || !cy) 
		return; 
 
	SIZE sz; 
	GetSizeOfBitmap(hSrcBitmap, &sz); 
 
	//ENG: Gets a max columns and rows of the images on the bitmap 
	//RUS: Получаем максимальное число колонок и строк изображений на битмапке 
	int nMaxCol = sz.cx / cx; 
	int nMaxRow = sz.cy / cy; 
	int nMaxImages = nMaxCol * nMaxRow; 
 
	if ((nIndex < nMaxImages) && nMaxCol && nMaxRow) 
	{ 
		//ENG: Gets an specified image from the bitmap 
		//RUS: Получаем указанное изображение из битмапа 
		HDC hSrcDC = ::CreateCompatibleDC(hDC); 
		HDC hDestDC = ::CreateCompatibleDC(hDC); 
		HBITMAP hIconBmp = ::CreateCompatibleBitmap(hDC, cx, cy); 
		HBITMAP hOldSrcBmp = (HBITMAP)::SelectObject(hSrcDC, hSrcBitmap); 
		HBITMAP hOldDestBmp = (HBITMAP)::SelectObject(hDestDC, hIconBmp); 
		::BitBlt(hDestDC, 0, 0, cx, cy, hSrcDC, (nIndex % nMaxCol) * cx, (nIndex / nMaxCol) * cy, SRCCOPY); 
		::SelectObject(hSrcDC, hOldSrcBmp); 
		::SelectObject(hDestDC, hOldDestBmp); 
		::DeleteDC(hSrcDC); 
		::DeleteDC(hDestDC); 
		DrawBitmap( hDC, x, y, dwWidth, dwHeight, hIconBmp,  
					bUseMask, crMask, dwEffect,  
					bShadow, dwCxShadow, dwCyShadow,  
					dwCxDepth, dwCyDepth, clrShadow); 
		::DeleteObject(hIconBmp); 
	} //if 
} //End of DrawImageList 
 
void CPPDrawManager::MaskToDepth(HDC hDC, DWORD dwWidth, DWORD dwHeight, HBITMAP hMask, double * pDepth, BOOL bGradient /* = FALSE */, DWORD dwDepthX /* = PPDRAWMANAGER_CXSHADOW */, DWORD dwDepthY /* = PPDRAWMANAGER_CYSHADOW */) 
{ 
	HDC hSrcDC = ::CreateCompatibleDC(hDC); 
	if (NULL == hSrcDC) 
	{ 
		::DeleteDC(hSrcDC); 
		hSrcDC = NULL; 
		return; 
	} //if 
 
	HDC hTempDC = ::CreateCompatibleDC(hDC); 
	if (NULL == hTempDC) 
	{ 
		::DeleteDC(hTempDC); 
		hTempDC = NULL; 
		return; 
	} //if 
	 
	//Creates Source DIB 
	LPBITMAPINFO lpbiSrc; 
	// Fill in the BITMAPINFOHEADER 
	lpbiSrc = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)]; 
	lpbiSrc->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	lpbiSrc->bmiHeader.biWidth = dwWidth; 
	lpbiSrc->bmiHeader.biHeight = dwHeight; 
	lpbiSrc->bmiHeader.biPlanes = 1; 
	lpbiSrc->bmiHeader.biBitCount = 32; 
	lpbiSrc->bmiHeader.biCompression = BI_RGB; 
	lpbiSrc->bmiHeader.biSizeImage = dwWidth * dwHeight; 
	lpbiSrc->bmiHeader.biXPelsPerMeter = 0; 
	lpbiSrc->bmiHeader.biYPelsPerMeter = 0; 
	lpbiSrc->bmiHeader.biClrUsed = 0; 
	lpbiSrc->bmiHeader.biClrImportant = 0; 
	 
	COLORREF* pSrcBits = NULL; 
	HBITMAP hSrcDib = CreateDIBSection ( 
		hSrcDC, lpbiSrc, DIB_RGB_COLORS, (void **)&pSrcBits, 
		NULL, NULL); 
	 
	if ((NULL != hSrcDib) && (NULL != pSrcBits)) 
	{ 
		HBITMAP hOldSrcBmp = (HBITMAP)::SelectObject (hSrcDC, hSrcDib); 
		HBITMAP hOldTempBmp = (HBITMAP)::SelectObject (hTempDC, hMask); 
		if (bGradient) 
		{ 
			if (!(dwDepthX & 0x1)) dwDepthX++; 
			if (!(dwDepthY & 0x1)) dwDepthY++; 
			::BitBlt(hSrcDC, 0, 0, dwWidth, dwHeight, hTempDC, 0, 0, WHITENESS); 
			::StretchBlt (hSrcDC, dwDepthX / 2, dwDepthY / 2, dwWidth - dwDepthX, dwHeight - dwDepthY, hTempDC, 0, 0, dwWidth, dwHeight, SRCCOPY); 
		} 
		else 
		{ 
			::BitBlt(hSrcDC, 0, 0, dwWidth, dwHeight, hTempDC, 0, 0, SRCCOPY); 
		} //if 
		::SelectObject (hTempDC, hOldTempBmp); 
		::SelectObject (hSrcDC, hOldSrcBmp); 
		 
		if (bGradient) 
		{ 
			SmoothMaskImage(dwWidth, dwHeight, pSrcBits, dwDepthX, dwDepthY, pDepth); 
		} 
		else 
		{ 
			for (DWORD pixel = 0; pixel < (dwHeight * dwWidth); pixel++, pSrcBits++, pDepth++) 
			{ 
				*pDepth = GetRValue(*pSrcBits) / 255; 
			} //for 
		} //if 
		delete lpbiSrc; 
		::DeleteObject(hSrcDib); 
	} //if 
	::DeleteDC(hTempDC); 
	::DeleteDC(hSrcDC); 
} //End MaskToDepth 
 
void CPPDrawManager::DarkenByDepth(HDC hDC, int x, int y, DWORD dwWidth, DWORD dwHeight, double * pDepth) 
{ 
	HDC hSrcDC = ::CreateCompatibleDC(hDC); 
	if (NULL == hSrcDC) 
	{ 
		::DeleteDC(hSrcDC); 
		hSrcDC = NULL; 
		return; 
	} //if 
	 
	//Creates Source DIB 
	LPBITMAPINFO lpbiSrc; 
	// Fill in the BITMAPINFOHEADER 
	lpbiSrc = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)]; 
	lpbiSrc->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	lpbiSrc->bmiHeader.biWidth = dwWidth; 
	lpbiSrc->bmiHeader.biHeight = dwHeight; 
	lpbiSrc->bmiHeader.biPlanes = 1; 
	lpbiSrc->bmiHeader.biBitCount = 32; 
	lpbiSrc->bmiHeader.biCompression = BI_RGB; 
	lpbiSrc->bmiHeader.biSizeImage = dwWidth * dwHeight; 
	lpbiSrc->bmiHeader.biXPelsPerMeter = 0; 
	lpbiSrc->bmiHeader.biYPelsPerMeter = 0; 
	lpbiSrc->bmiHeader.biClrUsed = 0; 
	lpbiSrc->bmiHeader.biClrImportant = 0; 
	 
	COLORREF* pSrcBits = NULL; 
	HBITMAP hSrcDib = CreateDIBSection ( 
		hSrcDC, lpbiSrc, DIB_RGB_COLORS, (void **)&pSrcBits, 
		NULL, NULL); 
	 
	if ((NULL != hSrcDib) && (NULL != pSrcBits)) 
	{ 
		HBITMAP hOldSrcBmp = (HBITMAP)::SelectObject (hSrcDC, hSrcDib); 
		::BitBlt(hSrcDC, 0, 0, dwWidth, dwHeight, hDC, x, y, SRCCOPY); 
		::SelectObject (hSrcDC, hOldSrcBmp); 
		 
		for (DWORD pixel = 0; pixel < (dwHeight * dwWidth); pixel++, pSrcBits++, pDepth++) 
		{ 
			*pSrcBits = DarkenColor(*pSrcBits, *pDepth); 
		} //for 
 
		hOldSrcBmp = (HBITMAP)::SelectObject (hSrcDC, hSrcDib); 
		::BitBlt(hDC, x, y, dwWidth, dwHeight, hSrcDC, 0, 0, SRCCOPY); 
		::SelectObject (hSrcDC, hOldSrcBmp); 
 
		delete lpbiSrc; 
		::DeleteObject(hSrcDib); 
	} //if 
	::DeleteDC(hSrcDC); 
} //DarkenByDepth 
 
void CPPDrawManager::SmoothMaskImage(const int ImageWidth,  
									 const int ImageHeight, 
									 const COLORREF* const pInitImg, 
									 const int KerWidth, 
									 const int KerHeight, 
									 double* const pResImg_R /*= NULL*/) 
{ 
	double* const pfBuff1 = new double[(ImageWidth  + KerWidth  - 1) *  
		(ImageHeight + KerHeight - 1)]; 
	double* const pfBuff2 = new double[(ImageWidth  + KerWidth  - 1) *  
		(ImageHeight + KerHeight - 1)]; 
	 
	// expanding initial image with a padding procdure 
	double* p = pfBuff1; 
	const COLORREF * pInitImg_It = pInitImg; 
	if(NULL != pResImg_R) 
	{ 
		for(int _i = - KerHeight/2; _i < ImageHeight +  KerHeight/2; _i++) 
		{ 
			for(int _j = -KerWidth/2; _j < ImageWidth + KerWidth/2;  _j++, p++) 
			{ 
				if ((_i >= 0) && (_i < ImageHeight) && (_j >= 0) && (_j < ImageWidth)) 
				{ 
					*p = GetRValue(*pInitImg_It++); 
					//					pInitImg_It++; 
				} 
				else 
					*p = 255; 
			} //for 
		} //for 
		 
		//--- 
		GetPartialSums(pfBuff1, 
			(ImageHeight + KerHeight - 1), 
			(ImageWidth  + KerWidth  - 1), 
			KerHeight, 
			KerWidth, 
			pfBuff2, 
			pResImg_R); 
		 
		for(int i = 0; i < ImageHeight*ImageWidth; i++) 
			*(pResImg_R + i) /= KerHeight*KerWidth*255; 
	} //if 
	 
	 
	delete []pfBuff1; 
	delete []pfBuff2; 
} //End SmoothMaskImage 
 
void CPPDrawManager::GetPartialSums(const double* const pM, 
									unsigned int nMRows, 
									unsigned int nMCols, 
									unsigned int nPartRows, 
									unsigned int nPartCols, 
									double* const pBuff, 
									double* const pRes) 
{ 
	const double* it1; 
	const double* it2; 
	const double* it3; 
	 
	double* pRowsPartSums; 
	const unsigned int nRowsPartSumsMRows = nMRows; 
	const unsigned int nRowsPartSumsMCols = nMCols - nPartCols + 1;	 
	 
	const unsigned int nResMRows = nMRows - nPartRows + 1; 
	const unsigned int nResMCols = nMCols - nPartCols + 1; 
	 
	 
	unsigned int i,j; 
	double s; 
	 
	// частичные суммы строк 
	it1          = pM; 
	pRowsPartSums = pBuff; 
	 
	for(i = 0; i < nMRows; i++) 
	{ 
		//------------- 
		it2 = it1; 
		s = 0; 
		for(j = 0;j < nPartCols;j++)s+=*it2++; 
		//------------- 
		it3 = it1; 
		*pRowsPartSums++ = s; 
		for(/*j = nPartCols*/; j < nMCols; j++) 
		{ 
			s+=*it2 - *it3; 
			*pRowsPartSums++ = s; 
			it2++; 
			it3++; 
		} //for 
		//-- 
		it1 += nMCols; 
	} //for 
	// формирование резуьтата 
	const double* it4; 
	const double* it5; 
	const double* it6; 
	 
	double* pResIt; 
	 
	it4    = pBuff; 
	pResIt = pRes; 
	 
	for(j = 0; j < nRowsPartSumsMCols; j++) 
	{ 
		pResIt = pRes + j; 
		//------------- 
		it5 = it4; 
		s = 0; 
		for(i = 0; i < nPartRows; i++) 
		{ 
			s += *it5; 
			it5 += nRowsPartSumsMCols;  
		} //for 
		//------------- 
		it6 = it4; 
		*pResIt = s; 
		pResIt += nRowsPartSumsMCols; 
		 
		for(; i < nRowsPartSumsMRows; i++) 
		{ 
			s += *it5 - *it6;//cout<left, lpRect->top, lpRect->right, lpRect->bottom, crLight, crDark, nStyle, nSize); 
} 
 
void CPPDrawManager::DrawRectangle(HDC hDC, int left, int top, int right, int bottom,  
								   COLORREF crLight, COLORREF crDark, int nStyle /* = PEN_SOLID */,  
								   int nSize /* = 1 */) 
{ 
	if ((PEN_NULL == nStyle) || (nSize < 1)) 
		return; 
 
	int nSysPenStyle = PS_SOLID; 
	int nDoubleLineOffset = nSize * 2; 
	switch (nStyle) 
	{ 
	case PEN_DASH: nSysPenStyle = PS_DASH; break; 
	case PEN_DOT: nSysPenStyle = PS_DOT; break; 
	case PEN_DASHDOT: nSysPenStyle = PS_DASHDOT; break; 
	case PEN_DASHDOTDOT: nSysPenStyle = PS_DASHDOTDOT; break; 
	case PEN_DOUBLE: 
	case PEN_SOLID: 
	default: 
		nSysPenStyle = PS_SOLID;  
		break; 
	} //switch 
 
	//Insideframe 
	left += nSize / 2; 
	top += nSize / 2; 
	right -= nSize / 2; 
	bottom -= nSize / 2; 
 
	//Creates a light pen 
	HPEN hPen = ::CreatePen(nSysPenStyle, nSize, crLight); 
	HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen); 
 
	//Draw light border 
	::MoveToEx(hDC, left, bottom, NULL); 
	::LineTo(hDC, left, top); 
	::LineTo(hDC, right, top); 
	if (PEN_DOUBLE == nStyle) 
	{ 
		::MoveToEx(hDC, left + nDoubleLineOffset, bottom - nDoubleLineOffset, NULL); 
		::LineTo(hDC, left + nDoubleLineOffset, top + nDoubleLineOffset); 
		::LineTo(hDC, right - nDoubleLineOffset, top + nDoubleLineOffset); 
	} //if 
 
	//Creates a dark pen if needed 
	if (crLight != crDark) 
	{ 
		SelectObject(hDC, hOldPen); 
		::DeleteObject(hPen); 
		hPen = ::CreatePen(nSysPenStyle, nSize, crDark); 
		hOldPen = (HPEN)::SelectObject(hDC, hPen); 
	} //if 
 
	//Draw dark border 
	::MoveToEx(hDC, right, top, NULL); 
	::LineTo(hDC, right, bottom); 
	::LineTo(hDC, left, bottom); 
	if (PEN_DOUBLE == nStyle) 
	{ 
		::MoveToEx(hDC, right - nDoubleLineOffset, top + nDoubleLineOffset, NULL); 
		::LineTo(hDC, right - nDoubleLineOffset, bottom - nDoubleLineOffset); 
		::LineTo(hDC, left + nDoubleLineOffset, bottom - nDoubleLineOffset); 
	} //if 
 
	SelectObject(hDC, hOldPen); 
	::DeleteObject(hPen); 
} //End DrawRectangle 
 
void CPPDrawManager::DrawLine(HDC hDC,  
							  int xStart, int yStart, int xEnd, int yEnd,  
							  COLORREF color, int nStyle /* = PEN_SOLID */,  
							  int nSize /* = 1 */) const 
{ 
	if ((PEN_NULL == nStyle) || (nSize < 1)) 
		return; 
	 
	int nSysPenStyle; 
	int nDoubleLineOffset = nSize * 2; 
	switch (nStyle) 
	{ 
	case PEN_DASH: nSysPenStyle = PS_DASH; break; 
	case PEN_DOT: nSysPenStyle = PS_DOT; break; 
	case PEN_DASHDOT: nSysPenStyle = PS_DASHDOT; break; 
	case PEN_DASHDOTDOT: nSysPenStyle = PS_DASHDOTDOT; break; 
	case PEN_DOUBLE: 
	case PEN_SOLID: 
	default: 
		nSysPenStyle = PS_SOLID;  
		break; 
	} //switch 
 
	HPEN hPen = ::CreatePen(nSysPenStyle, nSize, color); 
	HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen); 
 
	::MoveToEx(hDC, xStart, yStart, NULL); 
	::LineTo(hDC, xEnd, yEnd); 
	 
	if (PEN_DOUBLE == nStyle) 
	{ 
		if (xStart != xEnd) 
		{ 
			yStart += nDoubleLineOffset; 
			yEnd += nDoubleLineOffset; 
		} //if 
		 
		if (yStart != yEnd) 
		{ 
			xStart += nDoubleLineOffset; 
			xEnd += nDoubleLineOffset; 
		} //if 
		::MoveToEx(hDC, xStart, yStart, NULL); 
		::LineTo(hDC, xEnd, yEnd); 
	} //if 
	SelectObject(hDC, hOldPen); 
	::DeleteObject(hPen); 
} //End DrawLine