//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "ImgCopperFormUnit.h"
#include "GlobalUnit.h"
#include <System.IOUtils.hpp>
//---------------------------------------------------------------------------
static const COLORREF CLR_LINE_D = RGB( 18,  19,  21 ),
					  CLR_LINE_L = RGB( 140, 141, 145 );
#define TOP_LEFT     0
#define TOP_RIGHT    1
#define BOTTOM_LEFT  2
#define BOTTOM_RIGHT 3
#define TOP          4
#define BOTTOM       5
#define LEFT         6
#define RIGHT        7
#define CENTER       8
#define SAFE_DELETE(p) { if(p) { delete (p);     (p)=NULL; } }
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "PNGButton"
#pragma link "GeneralDialogPanel"
#pragma link "TextButton"
#pragma resource "*.dfm"
TImgCopperForm *ImgCopperForm;
//---------------------------------------------------------------------------
__fastcall TImgCopperForm::TImgCopperForm(TComponent* Owner, TRect rtCopper, TPicture *pPicSrc)
	: TForm(Owner)
{
	m_rtCopper = rtCopper;

	m_pPicSrc = new TPicture();
	if(pPicSrc && pPicSrc->Graphic->Width && pPicSrc->Graphic->Height ) {
		m_pPicSrc->Assign(pPicSrc);
	}

	m_pTBitmapLine = new TBitmap();
	m_pTBitmapLine->SetSize(4, 4);
	m_pTBitmapLine->Canvas->Brush->Style = bsClear;

	for( int indexY=0; indexY<4; indexY++ )
	{
		bool bLine = (indexY%2==0)?true:false;
		for( int indexX=0; indexX<4; indexX++ )
		{
			bool bEven = (indexX%2==0)?true:false;
			if(bLine) bEven = !bEven;

			m_pTBitmapLine->Canvas->Pixels[indexX][indexY] =
			(bEven==true)?CLR_LINE_D:CLR_LINE_L;
		}
	}

	// -----
	m_bPicDown = false;
	m_nResize  = 1;

	DragAcceptFiles(this->Handle, true);

	m_pTransSkinScollBar              = new TTransSkinScollBar(m_pPanelBKG);
	m_pTransSkinScollBar->Parent      = m_pPanelBKG;
	m_pTransSkinScollBar->SetBounds(0, 0, 14, 100);
	m_pTransSkinScollBar->Vertial     = false;
	m_pTransSkinScollBar->ThumbWidth  = 12;
	m_pTransSkinScollBar->OnChangePos = SizeChange;
	m_pTransSkinScollBar->BringToFront();

}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::FormCreate(TObject *Sender)
{
	//绘制圆角窗体
	FormResize(NULL);
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::FormClose(TObject *Sender, TCloseAction &Action)
{
	SAFE_DELETE(m_pTBitmapLine)
	SAFE_DELETE(m_pPicSrc)
	SAFE_DELETE(m_pTransSkinScollBar)
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::FormResize(TObject *Sender)
{
	m_pPanelBKG->Width = Width;
	m_pPanelBKG->Height = Height;
	m_pPanelBKG->Left = 0;
	m_pPanelBKG->Top = 0;

	// -----
	TRect rtBKG = TRect(1, 26, Width-1, 26+(Height-68));
	m_rtBKG = rtBKG;

	m_pPaintBoxSrc->Left    = 1;
	m_pPaintBoxSrc->Top     = rtBKG.Top;
	m_pPaintBoxSrc->Width   = Width-2;
	m_pPaintBoxSrc->Height  = rtBKG.Height();


	m_rtCopperEdge.Left   = rtBKG.Left+(rtBKG.Width()-m_rtCopper.Width())/2-4;
	m_rtCopperEdge.Top    = rtBKG.Top+(rtBKG.Height()-m_rtCopper.Height())/2-4;
	m_rtCopperEdge.Right  = m_rtCopperEdge.Left+m_rtCopper.Width()+8;
	m_rtCopperEdge.Bottom = m_rtCopperEdge.Top+m_rtCopper.Height()+8;

	m_pTransSkinScollBar->Width = Width/3;
	m_pTransSkinScollBar->Left
	= m_pPaintBoxSrc->Left+(m_pPaintBoxSrc->Width-m_pTransSkinScollBar->Width)/2;
	m_pTransSkinScollBar->Top
	= m_pPaintBoxSrc->Top+m_pPaintBoxSrc->Height -
	  m_pTransSkinScollBar->Height-8;
	HRGN hRgnSize =
	CreateRoundRectRgn( 0, 0,
						m_pTransSkinScollBar->Width+1,
						m_pTransSkinScollBar->Height+1,
						3, 3 );
	SetWindowRgn( m_pTransSkinScollBar->Handle, hRgnSize, false );
	DeleteObject( hRgnSize );

	m_pBtnCancel->Left = Width-m_pBtnCancel->Width-10;
	m_pBtnCancel->Top  = Height-m_pBtnCancel->Height-10;
	m_pBtnOk->Left = m_pBtnCancel->Left-m_pBtnOk->Width-10;
	m_pBtnOk->Top  = m_pBtnCancel->Top;

	m_btnChoose->Left = 10;
	m_btnChoose->Top  =
	m_pBtnCancel->Top+(m_pBtnCancel->Height-m_btnChoose->Height)/2;

	m_pPanelBKG->Caption = Caption;

	SetSrcPicRect();
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::SetCaption(String strCaption)
{
	m_pPanelBKG->Caption = strCaption;
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::m_pPaintBoxSrcPaint(TObject *Sender)
{
	int nWidth  = m_pPaintBoxSrc->Width;
	int nHeight = m_pPaintBoxSrc->Height;

	// 创建一个与显示设备兼容的内存设备
	HDC BufDC = CreateCompatibleDC(m_pPaintBoxSrc->Canvas->Handle);
	// 创建一个与显示设备兼容的位图
	HBITMAP BufBitmap = CreateCompatibleBitmap(m_pPaintBoxSrc->Canvas->Handle, nWidth, nHeight);
	// 将设备与位图关联
	SelectObject(BufDC, BufBitmap);
	// CreateCompatibleBitmap创建位图后数据初始化为0，而RGB(0,0,0)则表示是黑色
	// 这里需要清除其黑色背景，使其变为透明
	PerformEraseBackground(this, BufDC);
	// 临时的Canvas，用来画图用，但它并不是必须的，可以直接使用GDI函数来画图
	TCanvas *CanvasDraw = new TCanvas();
	// 关联到内存设备
	CanvasDraw->Handle = BufDC;

	//--------------------------------------
	CanvasDraw->Brush->Color = RGB(52, 56, 63);
	CanvasDraw->FillRect(TRect(0, 0, nWidth, nHeight));
	CanvasDraw->StretchDraw(m_rtSrc, m_pPicSrc->Graphic);

	int iLeft, iTop, iWidth, iHeight;
	CanvasDraw->Brush->Bitmap = m_pTBitmapLine;

	//left
	iLeft   = m_rtCopperEdge.Left-m_rtBKG.Left;
	iTop    = m_rtCopperEdge.Top-m_rtBKG.Top;
	iWidth  = 4;
	iHeight = m_rtCopperEdge.Height();
	CanvasDraw->FillRect( TRect(iLeft, iTop, iLeft+iWidth, iTop+iHeight) );

	//right
	iLeft   = m_rtCopperEdge.Left+m_rtCopperEdge.Width()-4-m_rtBKG.Left;
	iTop    = m_rtCopperEdge.Top-m_rtBKG.Top;
	iWidth  = 4;
	iHeight = m_rtCopperEdge.Height();
	CanvasDraw->FillRect( TRect(iLeft, iTop, iLeft+iWidth, iTop+iHeight) );

	//top
	iLeft   = m_rtCopperEdge.Left-m_rtBKG.Left;
	iTop    = m_rtCopperEdge.Top-m_rtBKG.Top;
	iWidth  = m_rtCopperEdge.Width();
	iHeight = 4;
	CanvasDraw->FillRect( TRect(iLeft, iTop, iLeft+iWidth, iTop+iHeight) );

	//bottom
	iLeft   = m_rtCopperEdge.Left-m_rtBKG.Left;
	iTop    = m_rtCopperEdge.Top+m_rtCopperEdge.Height()-4-m_rtBKG.Top;
	iWidth  = m_rtCopperEdge.Width();
	iHeight = 4;
	CanvasDraw->FillRect( TRect(iLeft, iTop, iLeft+iWidth, iTop+iHeight) );

	// 一次性将内存图像数据覆盖过去，因为跳过了擦除背景过程，所以避免了闪烁的问题
	BitBlt(m_pPaintBoxSrc->Canvas->Handle, 0, 0, nWidth, nHeight,
		   CanvasDraw->Handle, 0, 0, SRCCOPY);
	// 释放资源
	DeleteDC(BufDC);
	DeleteObject(BufBitmap);
	SAFE_DELETE(CanvasDraw)
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::m_pPaintBoxSrcMouseDown(TObject *Sender, TMouseButton Button,
		  TShiftState Shift, int X, int Y)
{
	m_bPicDown = true;
	m_ptDown = TPoint(X, Y);
	m_rtSrcMove = m_rtSrc;
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::m_pPaintBoxSrcMouseMove(TObject *Sender, TShiftState Shift,
          int X, int Y)
{
	if( m_bPicDown ) {

		int nLeft, nTop, nWidth, nHeight;

		nWidth  = m_rtSrcMove.Width();
		nHeight = m_rtSrcMove.Height();
		nLeft   = m_rtSrcMove.Left+X-m_ptDown.X;
		nTop    = m_rtSrcMove.Top+Y-m_ptDown.Y;

		m_rtSrc.Left   = nLeft;
		m_rtSrc.Top    = nTop;
		m_rtSrc.Right  = m_rtSrc.Left+nWidth;
		m_rtSrc.Bottom = m_rtSrc.Top+nHeight;

		m_pPaintBoxSrcPaint(NULL);
	}
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::m_pPaintBoxSrcMouseUp(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
{
	m_bPicDown = false;
	m_rtSrcMove = m_rtSrc;
	m_pTransSkinScollBar->Invalidate();
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::SizeChange(TObject *Sender)
{
	int nSize   = m_pTransSkinScollBar->SBTop + 1;
	if(m_nResize==nSize) return;
	m_nResize   = nSize;

	int nLMove, nTMove, nWMove, nHMove;
	nLMove = m_rtSrcMove.Left;
	nTMove = m_rtSrcMove.Top;
	nWMove = m_rtSrcMove.Width();
	nHMove = m_rtSrcMove.Height();

	int nLBac, nTBac, nWBac, nHBac;
	nLBac = m_rtSrcBac.Left;
	nTBac = m_rtSrcBac.Top;
	nWBac = m_rtSrcBac.Width();
	nHBac = m_rtSrcBac.Height();

	//方向
	int nStatusLoc;
	TPoint ptCenterSrcMove = TPoint(nLMove+nWMove/2, nTMove+nHMove/2);
	if( ptCenterSrcMove.X>m_rtSrcBac.Right &&
		ptCenterSrcMove.Y<m_rtSrcBac.Top )
	{
		nStatusLoc = TOP_RIGHT;

	}else if( ptCenterSrcMove.X>m_rtSrcBac.Right &&
			  ptCenterSrcMove.Y>m_rtSrcBac.Bottom )
	{
		nStatusLoc = BOTTOM_RIGHT;

	}else if( ptCenterSrcMove.X<m_rtSrcBac.Left &&
			  ptCenterSrcMove.Y>m_rtSrcBac.Bottom )
	{
		nStatusLoc = BOTTOM_LEFT;

	}else if( ptCenterSrcMove.X<m_rtSrcBac.Left &&
			  ptCenterSrcMove.Y<m_rtSrcBac.Top )
	{
		nStatusLoc = TOP_LEFT;

	}else if( ptCenterSrcMove.X>m_rtSrcBac.Right &&
			  ptCenterSrcMove.Y>m_rtSrcBac.Top &&
			  ptCenterSrcMove.Y<m_rtSrcBac.Bottom )
	{
		nStatusLoc = RIGHT;

	}else if( ptCenterSrcMove.X<m_rtSrcBac.Left &&
			  ptCenterSrcMove.Y>m_rtSrcBac.Top &&
			  ptCenterSrcMove.Y<m_rtSrcBac.Bottom )
	{
		nStatusLoc = LEFT;

	}else if( ptCenterSrcMove.Y>m_rtSrcBac.Bottom &&
			  ptCenterSrcMove.X>m_rtSrcBac.Left &&
			  ptCenterSrcMove.X<m_rtSrcBac.Right )
	{
		nStatusLoc = BOTTOM;

	}else if( ptCenterSrcMove.Y<m_rtSrcBac.Top &&
			  ptCenterSrcMove.X>m_rtSrcBac.Left &&
			  ptCenterSrcMove.X<m_rtSrcBac.Right )
	{
		nStatusLoc = TOP;

	}else{

		nStatusLoc = CENTER;
	}

	//得到缩放焦点
	TPoint ptFocus;
	if( CENTER==nStatusLoc ) {

		 ptFocus = ptCenterSrcMove;

	}else if( TOP_RIGHT==nStatusLoc ) {

		 ptFocus = TPoint(nLMove+nWMove/4, nTMove+nHMove*3/4);

	}else if( BOTTOM_RIGHT==nStatusLoc ) {

		 ptFocus = TPoint(nLMove+nWMove/4, nTMove+nHMove/4);

	}else if( BOTTOM_LEFT==nStatusLoc ) {

		 ptFocus = TPoint(nLMove+nWMove*3/4, nTMove+nHMove/4);

	}else if( TOP_LEFT==nStatusLoc ) {

		 ptFocus = TPoint(nLMove+nWMove*3/4, nTMove+nHMove*3/4);

	}else if( RIGHT==nStatusLoc ) {

		 ptFocus = TPoint(nLMove+nWMove/4, nTMove+nHMove/2);

	}else if( LEFT==nStatusLoc ) {

		 ptFocus = TPoint(nLMove+nWMove*3/4, nTMove+nHMove/2);

	}else if( BOTTOM==nStatusLoc ) {

		 ptFocus = TPoint(nLMove+nWMove/2, nTMove+nHMove/4);

	}else if( TOP==nStatusLoc ) {

		 ptFocus = TPoint(nLMove+nWMove/2, nTMove+nHMove*3/4);

	}

	//进行缩放处理
	int nLSrc, nTSrc, nWSrc, nHSrc;
	nWSrc   = nWBac*nSize;
	nHSrc   = nHBac*nSize;
	if( CENTER==nStatusLoc ) {

		nLSrc   = ptFocus.X - nWSrc/2;
		nTSrc   = ptFocus.Y - nHSrc/2;

	}else if( TOP_RIGHT==nStatusLoc ) {

		nLSrc = ptFocus.X - nWSrc/4;
		nTSrc = ptFocus.Y - nHSrc*3/4;

	}else if( BOTTOM_RIGHT==nStatusLoc ) {

		nLSrc = ptFocus.X - nWSrc/4;
		nTSrc = ptFocus.Y - nHSrc/4;

	}else if( BOTTOM_LEFT==nStatusLoc ) {

		nLSrc = ptFocus.X - nWSrc*3/4;
		nTSrc = ptFocus.Y - nHSrc/4;

	}else if( TOP_LEFT==nStatusLoc ) {

		nLSrc = ptFocus.X - nWSrc*3/4;
		nTSrc = ptFocus.Y - nHSrc*3/4;

	}else if( RIGHT==nStatusLoc ) {

		nLSrc = ptFocus.X - nWSrc/4;
		nTSrc = ptFocus.Y - nHSrc/2;

	}else if( LEFT==nStatusLoc ) {

		nLSrc = ptFocus.X - nWSrc*3/4;
		nTSrc = ptFocus.Y - nHSrc/2;

	}else if( BOTTOM==nStatusLoc ) {

		nLSrc = ptFocus.X - nWSrc/2;
		nTSrc = ptFocus.Y - nHSrc/4;

	}else if( TOP==nStatusLoc ) {

		nLSrc = ptFocus.X - nWSrc/2;
		nTSrc = ptFocus.Y - nHSrc*3/4;
	}

	m_rtSrc.Left   = nLSrc;
	m_rtSrc.Top    = nTSrc;
	m_rtSrc.Right  = m_rtSrc.Left+nWSrc;
	m_rtSrc.Bottom = m_rtSrc.Top+nHSrc;

	m_pPaintBoxSrcPaint(NULL);

	m_pTransSkinScollBar->Refresh();
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::SetSrcPicRect()
{
	int nLeft, nTop, nWidth, nHeight;
	if( m_pPicSrc ) {

		int nWidthLarge   = -1;
		int nWidthCopper  = m_rtCopper.Width();
		int nHeightCopper = m_rtCopper.Height();
		nWidth  = m_pPicSrc->Width;
		nHeight = m_pPicSrc->Height;

		if( nWidth<m_rtCopper.Width() ) {
			nLeft        = (nWidthCopper-nWidth)/2;
		}else{
			nWidthLarge  = nWidth;
			nLeft        = 0;
			nWidth       = nWidthCopper;
		}

		if( -1!=nWidthLarge ) {
			nHeight = nHeight*nWidth/nWidthLarge;
		}
		nTop  = (nHeightCopper-nHeight)/2;


		m_rtSrc.Left   = nLeft+(m_rtCopperEdge.Left-m_pPaintBoxSrc->Left)+4;
		m_rtSrc.Top    = nTop+(m_rtCopperEdge.Top-m_pPaintBoxSrc->Top)+4;
		m_rtSrc.Right  = m_rtSrc.Left+nWidth;
		m_rtSrc.Bottom = m_rtSrc.Top+nHeight;
		m_rtSrcBac  = m_rtSrc;
		m_rtSrcMove = m_rtSrc;

		if( -1!=nWidthLarge )
			m_pTransSkinScollBar->SBTotal = m_pPicSrc->Width*5/m_rtSrc.Width();
		else
			m_pTransSkinScollBar->SBTotal = 5;
		m_pTransSkinScollBar->SBShow      = 2;
		m_pTransSkinScollBar->SBTop       = 0;
		m_nResize = 1;
	}
}
//---------------------------------------------------------------------------
bool __fastcall TImgCopperForm::SetSrcPic(String fileName)
{
	TMemoryStream *memoryStream = new TMemoryStream();
	memoryStream->Position = 0;
	memoryStream->LoadFromFile(fileName);

	if( !GetPicType(fileName, memoryStream, true) ){
		SAFE_DELETE(memoryStream)
		return false;
	}else {

		TPicture *pTPicture = new TPicture();
		try{
			pTPicture->LoadFromFile(fileName);
		}catch(Exception &e){
			SAFE_DELETE(pTPicture)
			SAFE_DELETE(memoryStream)
			return false;
		}

		if( m_pPicSrc ) {

			m_pPicSrc->Assign(pTPicture);
			SetSrcPicRect();
			m_pPaintBoxSrcPaint(NULL);
			m_pTransSkinScollBar->Invalidate();
			SAFE_DELETE(pTPicture)
		}
	}

	SAFE_DELETE(memoryStream)
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::WMDRopFiles (TMessage& Msg)
{
	wchar_t wcFileName[256];
	int iCount = DragQueryFile((HDROP)Msg.WParam, 0xffffffff, wcFileName , 256);

    for (int index=0; index<iCount; index++)
	{
		DragQueryFile((HDROP )Msg.WParam, index, wcFileName , 256);
		String fileName = wstr2str(wcFileName).c_str();

		if( SetSrcPic(fileName) ) break;
	}

	DragFinish((HDROP)Msg.WParam);
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::m_btnChooseClick(TObject *Sender)
{
	String strPicPath;

	//     -----
	TOpenDialog *pDlg = new TOpenDialog(NULL);
	pDlg->Title       = "打开图片";
	pDlg->Options << ofFileMustExist;
//	pDlg->FileName    = ExtractFileName(L"");
//	pDlg->InitialDir  = ExtractFilePath(L"");
	pDlg->Filter      = "jpg文件 (*.jpg)|*.JPG|png文件 (*.png)|*.PNG|bmp文件 (*.bmp)|*.BMP";
	pDlg->DefaultExt  = "jpg";
	if ( pDlg->Execute(Handle) ) {
		strPicPath = pDlg->FileName.c_str();
	}
	SAFE_DELETE(pDlg);

	if( !strPicPath.IsEmpty() ){
		SetSrcPic(strPicPath);
	}
}
//---------------------------------------------------------------------------
void __fastcall TImgCopperForm::m_pBtnOkClick(TObject *Sender)
{
	int iLeft, iTop, iWidth, iHeight;
	iLeft   = 0;
	iTop    = 0;
	iWidth  = m_rtCopper.Width();
	iHeight = m_rtCopper.Height();

	TBitmap *pTBitmapCopper = new TBitmap();
	pTBitmapCopper->SetSize(iWidth, iHeight);
	pTBitmapCopper->Canvas->Brush->Color = RGB(0, 0, 0);
	pTBitmapCopper->Canvas->FillRect(TRect(iLeft, iTop, iLeft+iWidth, iTop+iHeight));

	iWidth  = m_rtSrc.Width();
	iHeight = m_rtSrc.Height();

	m_rtSrc.Left   -= m_rtCopperEdge.Left-m_pPaintBoxSrc->Left+4;
	m_rtSrc.Top    -= m_rtCopperEdge.Top-m_pPaintBoxSrc->Top+4;
	m_rtSrc.Right   = m_rtSrc.Left+iWidth;
    m_rtSrc.Bottom  = m_rtSrc.Top+iHeight;
	pTBitmapCopper->Canvas->StretchDraw(m_rtSrc, m_pPicSrc->Graphic);
	m_strCopperPath = g_strUserPath.c_str();
	m_strCopperPath += L"temp\\";
	if(!DirectoryExists(m_strCopperPath, false))
		ForceDirectories(m_strCopperPath);
	m_strCopperPath += L"copper.jpg";

	TJPEGImage *pTJPEGImage = new TJPEGImage();
	pTJPEGImage->Assign(pTBitmapCopper);
	pTJPEGImage->SaveToFile( m_strCopperPath );
	SAFE_DELETE(pTJPEGImage);
	SAFE_DELETE(pTBitmapCopper);
}
//---------------------------------------------------------------------------




