#include "stdafx.h"
#include "CCompatibleDC.h"

#ifndef MAX
#define MAX(a,b)            (((a) > (b)) ? (a) : (b))
#endif

#ifndef MIN
#define MIN(a,b)            (((a) < (b)) ? (a) : (b))
#endif


CCompatibleDC::CCompatibleDC()
{
}


CCompatibleDC::~CCompatibleDC()
{
}


BOOL DisplayBMP(CDC* pDC, int nX1, int nY1, int nXX, int nYY, CString strBMPFile, BOOL bStretch)
{
	OFSTRUCT of;
	unsigned fh = OpenFile((char const*)strBMPFile, &of, OF_READ);
	if (fh == -1) return FALSE;

	DWORD size = (DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
	HANDLE hDIBInfo = GlobalAlloc(GMEM_MOVEABLE, size);

	BITMAPFILEHEADER bf;
	LPBITMAPINFOHEADER lpbi;
	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIBInfo);
	_lread(fh, (LPSTR)&bf, sizeof(bf));
	_lread(fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER));
	WORD nClrs = (WORD)lpbi->biClrUsed;
	size = ((((lpbi->biWidth*lpbi->biBitCount) + 31)&~31) >> 3)*lpbi->biHeight;
	if (nClrs == 0 && lpbi->biBitCount != 24) nClrs = 1 << lpbi->biBitCount;
	if (lpbi->biClrUsed == 0) lpbi->biClrUsed = (DWORD)nClrs;
	if (lpbi->biSizeImage == 0) lpbi->biSizeImage = size;

	WORD Size = (WORD)lpbi->biSize;
	WORD Width = (WORD)lpbi->biWidth;
	WORD Height = (WORD)lpbi->biHeight;
	WORD ClrUsed = (WORD)lpbi->biClrUsed;
	WORD BitCount = (WORD)lpbi->biBitCount;
	DWORD SizeImage = lpbi->biSizeImage;
	WORD SizeRGB = nClrs * sizeof(RGBQUAD);
	WORD SizeHeader = Size + SizeRGB;

	GlobalUnlock(hDIBInfo);
	hDIBInfo = GlobalReAlloc(hDIBInfo, SizeHeader + SizeImage, 0);
	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIBInfo);
	_lread(fh, (LPSTR)(lpbi)+Size, SizeRGB);
	if (bf.bfOffBits != 0L) _llseek(fh, bf.bfOffBits, SEEK_SET);

	DWORD ul = SizeImage;
	BYTE *hp = (BYTE *)((LPSTR)lpbi + SizeHeader);
	while (ul > 30000L)
	{
		_lread(fh, (LPSTR)hp, 30000L);
		ul -= 30000L;
		hp += 30000L;
	}
	_lread(fh, (LPSTR)hp, (WORD)ul);
	_lclose(fh);

	HPALETTE hPalette = NULL, hOldPal = NULL;
	HANDLE hPalHeader = NULL;

	HDC hDC = pDC->m_hDC;
	LPBITMAPINFOHEADER lpHeader = lpbi;
	WORD wDIBUse = DIB_RGB_COLORS;

	if (ClrUsed)
	{
		WORD size = sizeof(LOGPALETTE) + ClrUsed * sizeof(PALETTEENTRY);
		NPLOGPALETTE npPal = (NPLOGPALETTE)LocalAlloc(LMEM_FIXED, size);
		npPal->palVersion = 0x300;
		npPal->palNumEntries = ClrUsed;
		RGBQUAD FAR *lpRGB = (RGBQUAD FAR *)((LPSTR)lpbi + Size);
		for (WORD i = 0; i < ClrUsed; i++, lpRGB++)
		{
			npPal->palPalEntry[i].peRed = lpRGB->rgbRed;
			npPal->palPalEntry[i].peGreen = lpRGB->rgbGreen;
			npPal->palPalEntry[i].peBlue = lpRGB->rgbBlue;
			npPal->palPalEntry[i].peFlags = 0;
		}
		hPalette = CreatePalette((LPLOGPALETTE)npPal);
		LocalFree((HANDLE)npPal);
		hOldPal = SelectPalette(hDC, hPalette, FALSE);
		RealizePalette(hDC);

		if (BitCount != 24)
		{
			size = Size + ClrUsed * sizeof(WORD);
			hPalHeader = GlobalAlloc(GMEM_MOVEABLE, size);
			LPBITMAPINFOHEADER lpPalInfo;
			lpPalInfo = (LPBITMAPINFOHEADER)GlobalLock(hPalHeader);
			*lpPalInfo = *lpbi;
			WORD FAR *lpTable = (WORD FAR *)((LPSTR)lpPalInfo + Size);
			for (WORD i = 0; i < ClrUsed; i++) *lpTable++ = i;
			GlobalUnlock(hPalHeader);
			lpHeader = (LPBITMAPINFOHEADER)GlobalLock(hPalHeader);
			wDIBUse = DIB_PAL_COLORS;
		}
	}

	HDC hMemDC = CreateCompatibleDC(hDC);
	HBITMAP hDDBitmap = CreateCompatibleBitmap(hDC, Width, Height);
	SetDIBits(hDC, hDDBitmap, 0, Height, (LPSTR)lpbi + SizeHeader,
		(LPBITMAPINFO)lpHeader, wDIBUse);
	HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hDDBitmap);
	if (bStretch)
	{
		StretchBlt(hDC, nX1, nY1, nXX, nYY, hMemDC, 0, 0, Width, Height, SRCCOPY);
	}
	else
	{
		Width = MIN(Width, nXX);
		Height = MIN(Height, nYY);
		BitBlt(hDC, nX1, nY1, Width, Height, hMemDC, 0, 0, SRCCOPY);
	}
	SelectObject(hMemDC, hOldBitmap);
	DeleteDC(hMemDC);
	DeleteObject(hDDBitmap);

	if (ClrUsed)
	{
		SelectPalette(hDC, hOldPal, FALSE);
		DeleteObject(hPalette);
		if (BitCount != 24)
		{
			GlobalUnlock(hPalHeader);
			GlobalFree(hPalHeader);
		}
	}

	GlobalUnlock(hDIBInfo);
	GlobalFree(hDIBInfo);
	return TRUE;
}


void DrawColorButton(LPDRAWITEMSTRUCT lpDIS, COLORREF clrButton)
{
	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
	CRect rectButton = lpDIS->rcItem;
	UINT nStyle = DFCS_BUTTONPUSH;
	if (lpDIS->itemState & ODS_SELECTED) nStyle |= DFCS_PUSHED;
	if (lpDIS->itemState & ODS_DISABLED) nStyle |= DFCS_INACTIVE;
	pDC->DrawFrameControl(rectButton, DFC_BUTTON, nStyle);
	CRect rectColor = lpDIS->rcItem;
	rectColor.InflateRect(-1, -1, -1, -1);
	if (lpDIS->itemState & ODS_SELECTED) rectColor.InflateRect(-1, -1, 1, 1);
	if (lpDIS->itemState & ODS_DISABLED)
	{
		CPen pen(PS_SOLID, 1, RGB(128, 128, 128));
		CPen* pOldPen = pDC->SelectObject(&pen);
		pDC->SetBkColor(RGB(192, 192, 192));
		pDC->SetTextColor(clrButton);
		CBrush* pBrush = pDC->GetHalftoneBrush();
		CBrush* pOldBrush = pDC->SelectObject(pBrush);
		pDC->Rectangle(rectColor);
		pDC->SelectObject(pOldBrush);
		pDC->SelectObject(pOldPen);
	}
	else
	{
		CBrush brush(clrButton);
		CBrush* pOldBrush = pDC->SelectObject(&brush);
		pDC->SelectStockObject(BLACK_PEN);
		pDC->Rectangle(rectColor);
		pDC->SelectObject(pOldBrush);
	}
}


void CCompatibleDC::Create(CDC* pDC)
{
	m_pDrawDC = pDC;
	// 获取裁剪区域;
	m_pDrawDC->GetClipBox(m_rect);
	m_rect.right++;
	m_rect.bottom++;
	// 创建兼容DC;
	CreateCompatibleDC(m_pDrawDC);
	// 如果存在裁剪区域;
	//if (m_rect.Width() > 0)
	if(!m_rect.IsRectEmpty() && !m_rect.IsRectNull())
	{
		// 创建兼容画布;
		m_bitmap.CreateCompatibleBitmap(m_pDrawDC, m_rect.Width(), m_rect.Height());
		m_pOldBitmap = SelectObject(&m_bitmap);
		OffsetViewportOrg(-m_rect.left, -m_rect.top);
		IntersectClipRect(m_rect);
		CPoint point(0, 0);
		LPtoDP(&point);
		SetBrushOrg(point);

		//2011-11-01 add
		DeleteObject(m_bitmap);
	}

	//2011-11-02 add
	DeleteObject(m_pDrawDC);
}

void CCompatibleDC::Destroy(void)
{
	SelectClipRgn(NULL);
	SetViewportOrg(0, 0);
	m_pDrawDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), this, 0, 0, SRCCOPY);
	SelectObject(m_pOldBitmap);
}

void CCompatibleDC::Destroy(CRect rect)
{
	SelectClipRgn(NULL);
	SetViewportOrg(0, 0);

	CRect rc1, rc2, rc3, rc4;
	//////////////////////////////////////
	//				2					//
	//									//
	//		///////////////				//
	//	1	//			//		3		//
	//		//			//				//
	//		//////////////				//
	//									//
	//				4					//
	//									//
	//////////////////////////////////////
	rc1.left = m_rect.left;
	rc1.right = rect.left;
	rc1.top = m_rect.top;
	rc1.bottom = m_rect.bottom;

	rc2.left = m_rect.left;
	rc2.right = m_rect.right;
	rc2.top = m_rect.top;
	rc2.bottom = rect.top;

	rc3.left = rect.right;
	rc3.right = m_rect.right;
	rc3.top = m_rect.top;
	rc3.bottom = m_rect.bottom;

	rc4.left = m_rect.left;
	rc4.right = m_rect.right;
	rc4.top = rect.bottom;
	rc4.bottom = m_rect.bottom;

	m_pDrawDC->BitBlt(rc1.left, rc1.top, rc1.Width() / 1, rc1.Height(), this, 0, 0, SRCCOPY);
	m_pDrawDC->BitBlt(rc2.left, rc2.top, rc2.Width() / 1, rc2.Height(), this, 0, rc2.top, SRCCOPY);
	m_pDrawDC->BitBlt(rc3.left, rc3.top, rc3.Width() / 1, rc3.Height(), this, rc3.left, rc3.top, SRCCOPY);
	m_pDrawDC->BitBlt(rc4.left, rc4.top, rc4.Width() / 1, rc4.Height(), this, 0, rc4.top, SRCCOPY);
	SelectObject(m_pOldBitmap);
	//if( m_rect.left<rect.left )
	//{
	//	rc1.left = m_rect.left;
	//	rc1.right = m_rect.right;
	//	rc1.top = m_rect.top;
	//	rc1.bottom = rect.top;

	//	rc2.left = m_rect.left;
	//	rc2.right = rect.left;
	//	rc2.top = m_rect.top;
	//	rc2.bottom = m_rect.bottom;

	//	rc3.left = rect.right;
	//	rc3.right = m_rect.right;
	//	rc3.top = m_rect.top;
	//	rc3.bottom = m_rect.bottom;

	//	rc4.left = m_rect.left;
	//	rc4.right = m_rect.right;
	//	rc4.top = rect.bottom;
	//	rc4.bottom = m_rect.bottom;

	//m_pDrawDC->BitBlt(rc1.left,rc1.top,rc1.Width()/1,rc1.Height(),this, 0,0, SRCCOPY);
	//m_pDrawDC->BitBlt(rc2.left,rc2.top,rc2.Width()/1,rc2.Height(),this, 0,rc2.top, SRCCOPY);
	//m_pDrawDC->BitBlt(rc3.left,rc3.top,rc3.Width()/1,rc3.Height(),this, rc3.left,rc3.top, SRCCOPY);
	//m_pDrawDC->BitBlt(rc4.left,rc4.top,rc4.Width()/1,rc4.Height(),this, 0,rc4.top, SRCCOPY);
	//SelectObject(m_pOldBitmap);


}