// DXDDraw.cpp: implementation of the CDXDDraw class.
//
//////////////////////////////////////////////////////////////////////

#include "DXDDraw.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDXDDraw::CDXDDraw()
{
	ClassInit();
}

CDXDDraw::~CDXDDraw()
{
	ClassRelease();
}

void CDXDDraw::ClassInit()
{
	m_pDDraw=NULL;			// 다이렉트 드로우..
	m_pDDSPrimary=NULL;		// 표면.
	m_pDDSBack=NULL;		// 백표면.
	m_pClipper=NULL;		// 클리퍼.
	m_DDPixelFormat;		// 픽셀 포맷을 알아내기 위한 변수.
	m_hWnd=NULL;
	m_BitPerPixel=0;

	SAFE_INIT(m_DDPixelFormat, DDPIXELFORMAT);
	m_MaxScrSz.cx=0;m_MaxScrSz.cy=0;
	SetRect(&m_MaxScrRt,0,0,0,0);

	m_bFullModeOn=false;
	m_bDrawOn=true;	
	m_hWnd=NULL;	

	m_FrmCur=m_Fps=m_TimeCur=m_TimeOld=0;	// 프레임 시간과 관련된 것...
	ZeroMemory(m_TimeStr, strlen(m_TimeStr));
}

void CDXDDraw::ClassRelease()
{
	for(long i=0;i<SURFACE_MAX_NUM;i++)
		m_Surface[i].Release();						// 버퍼 서피스 해제..

	SAFE_RELEASE(m_pClipper);						// 클리퍼 해제.
	if(!m_bFullModeOn)	SAFE_RELEASE(m_pDDSBack);	// 풀화면이 아니면 백화면 해제.
	SAFE_RELEASE(m_pDDSPrimary);					// 실제 화면해제.
	SAFE_RELEASE(m_pDDraw);							// 다이렉트 드로우 해제.

	m_hWnd=NULL;
}

// 함수들....
bool CDXDDraw::DDrawCreate(HWND hwnd, long width, long height, long bitPerPixel, bool bFullModeOn)
{
    DDSCAPS2                    ddscaps;

	if(hwnd == NULL)	return FALSE;
	if(!(((width==640)&&(height==480)) || 
		 ((width==800)&&(height==600)) || 
		 ((width==1024)&&(height==768))) &&
		 ((bitPerPixel==16)||(bitPerPixel==24)||(bitPerPixel==32)))
	{
		char tempMsg[255] = { NULL, };
		wsprintf(tempMsg, "[ %d X %d ] %d bit 는 DirectDraw 에서 지원하지 않습니다.", width, height, bitPerPixel);
		MessageBox(hwnd, tempMsg, NULL, NULL);
		return FALSE;
	}

	// 다이렉트 드로우 초기화.........
	if(DD_OK!=DirectDrawCreateEx(NULL, (VOID**)&m_pDDraw, IID_IDirectDraw7, NULL))	return false;
	if(bFullModeOn)
	{	if(DD_OK!=m_pDDraw->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN))	return false;	}
	else
	{	if(DD_OK!=m_pDDraw->SetCooperativeLevel(hwnd, DDSCL_NORMAL))	return false;	}

	// 디스플레이 모드 세팅.
	if(bFullModeOn)
    if(DD_OK!=m_pDDraw->SetDisplayMode(width, height, bitPerPixel, 0, 0)) return false;

	if(bFullModeOn)								// 표면의 생성.........
	{
	    DDSURFACEDESC2		ddsd;
		ZeroMemory(&ddsd, sizeof(ddsd));		// 주 표면 만들기..
		ddsd.dwSize = sizeof(ddsd);
		ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
		ddsd.ddsCaps.dwCaps =DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;
		ddsd.dwBackBufferCount = 1;
		if(DD_OK!=m_pDDraw->CreateSurface(&ddsd, &m_pDDSPrimary, NULL)) return false;
		
		ZeroMemory(&ddscaps, sizeof(ddscaps));	// 백 버퍼 표면 만들기.
		ddscaps.dwCaps=DDSCAPS_BACKBUFFER;
		if(DD_OK!=m_pDDSPrimary->GetAttachedSurface(&ddscaps, &m_pDDSBack)) return false;
	}
	else
	{
	    DDSURFACEDESC2		ddsd;
		ZeroMemory(&ddsd, sizeof(ddsd));		// 주 표면 만들기..
		ddsd.dwSize = sizeof(ddsd);
		ddsd.dwFlags = DDSD_CAPS;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
		if(DD_OK!=m_pDDraw->CreateSurface(&ddsd, &m_pDDSPrimary, NULL))	return false;

		ZeroMemory(&ddsd,sizeof(ddsd));			// 백 버퍼 표면 만들기.
		ddsd.dwSize=sizeof(ddsd);
		ddsd.dwFlags=DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
		ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
		ddsd.dwWidth=width;
		ddsd.dwHeight=height;
		ddsd.dwBackBufferCount=0;
		if(DD_OK!=m_pDDraw->CreateSurface(&ddsd, &(m_pDDSBack), NULL)) return false;
	}

		
    // 클리퍼의 생성........
	if(!bFullModeOn)
	{
		if(DD_OK!=m_pDDraw->CreateClipper(0, &m_pClipper, NULL))	return false;
    	if(DD_OK!=m_pClipper->SetHWnd(0, hwnd))						return false;
    	if(DD_OK!=m_pDDSPrimary->SetClipper(m_pClipper))			return false;
	}

	m_BitPerPixel=PixelFormatCheck();	// 픽셀 포맷 구하기.		(15, 16, 24비트 체크)

	// 화면모드 체크........
	m_bFullModeOn=bFullModeOn;
	m_MaxScrSz.cx=width;
	m_MaxScrSz.cy = height;
	SetRect(&m_MaxScrRt, 0, 0, width, height);
	m_hWnd=hwnd;

	FillColor(m_MaxScrRt, 0);
	Flip();
	return true;
}


void CDXDDraw::Flip()
{
	// 스킵이면 넘어가기.
	#ifdef	FPS_SHOW_ON
	FpsShow();
	#endif

	// 화면 플리핑...
	if(m_bFullModeOn)
	{
		long ret=false;
		ret=m_pDDSPrimary->Flip(NULL, 0);
		if(ret==DD_OK)	return;
		if(ret==DDERR_SURFACELOST)
		{
			RestoreAll();
			return;
		}
		if(ret!=DDERR_WASSTILLDRAWING)	return;
	}
	else
	{
		RECT	destRect;
		long	ret;
		POINT   pt;
		GetClientRect(m_hWnd, &destRect);
		pt.x = pt.y = 0;
		ClientToScreen(m_hWnd, &pt);
		OffsetRect(&destRect, pt.x, pt.y);

		while(true)
		{
			ret=m_pDDSPrimary->Blt(&destRect, m_pDDSBack, &m_MaxScrRt, 0, NULL);

			if(ret==DD_OK)					return;;
			if(ret!=DDERR_WASSTILLDRAWING)	return;
			if(ret==DDERR_SURFACELOST)
			{
				RestoreAll();		return;
			}
		}
	}
}

	


void CDXDDraw::PutString(long x, long y, char * pStr, COLORREF col)
{
	HDC hdc=NULL;
	
	if(FAILED(m_pDDSBack->GetDC (&hdc)))
	{
		AfxErrMsg("PutString()-GetDc() 실패.");
		return;
	}

	SetBkMode(hdc, TRANSPARENT);
	SetTextColor(hdc, col);
	TextOut(hdc, x, y, pStr, strlen(pStr));
	if(hdc)	m_pDDSBack -> ReleaseDC (hdc);
}

void CDXDDraw::PutString(long x, long y, char * pStr)
{
	PutString(x, y, pStr, RGB(0,0,0));
}

void CDXDDraw::PutCheckString(long x, long y, char *pStr)
{
	HDC hdc=NULL;
	
	if(FAILED(m_pDDSBack->GetDC (&hdc)))
	{
		AfxErrMsg("PutString()-GetDc() 실패.");
		return;
	}

	SetBkColor(hdc, RGB(255,255,255));
	SetTextColor(hdc, RGB(0,0,0));
	TextOut(hdc, x, y, pStr, strlen(pStr));
	if(hdc)	m_pDDSBack -> ReleaseDC (hdc);
}

bool CDXDDraw::SurfaceCreate(long nSurface, long width, long height)
{
	m_Surface[nSurface].Release();	// 초기화를 시킴...

	DDSURFACEDESC2 ddsd;	//	표면에 대한 정보를 담는 구조체.......
	ZeroMemory(&ddsd,sizeof(ddsd));
	ddsd.dwSize=sizeof(ddsd);
	ddsd.dwFlags=DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
	//ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
	ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
	ddsd.dwWidth=width;
	ddsd.dwHeight=height;
	ddsd.dwBackBufferCount=0;

	// 표면 생성.........
	if((DD_OK!=m_pDDraw->CreateSurface(&ddsd, &(m_Surface[nSurface].pSurface), NULL))||(!m_Surface[nSurface].pSurface))
	{
		m_Surface[nSurface].Release();
		char str[256];
		wsprintf(str, "%03d 번 오프스크린 생성 실패", nSurface);
		AfxErrMsg(str);
		return false;
	}
	m_Surface[nSurface].Height=height;
	m_Surface[nSurface].Width=width;
	return true;
}

bool CDXDDraw::SurfaceCreate(long nSurface, char * pFileName, COLORREF col)
{
	if(!SurfaceCreate(nSurface, pFileName))	return false;
	if(!ColorKeySet(nSurface, col))		return false;
	return true;
}

bool CDXDDraw::SurfaceCreate(long nSurface, char * pFileName)
{
	m_Surface[nSurface].Release();
	SIZE sz;
	sz=BmpSizeGet(pFileName);
	if((sz.cx<=0)||(sz.cy<=0))	return false;

	m_Surface[nSurface].pSurface=BmpLoad(pFileName, sz.cx, sz.cy);
	if(!m_Surface[nSurface].pSurface)
	{
		char str[256];
		wsprintf(str, "%s 파일열기 실패.", pFileName);
		AfxErrMsg(str);
		return false;
	}
	wsprintf(m_Surface[nSurface].FileName, pFileName);
	m_Surface[nSurface].Height=sz.cx;
	m_Surface[nSurface].Width=sz.cy;

	return true;
}

bool CDXDDraw::ColorKeySet(long nSurface, COLORREF col)
{
	DDCOLORKEY	colKey;
	colKey.dwColorSpaceHighValue=col;
	colKey.dwColorSpaceLowValue=col;
	if(DD_OK==m_Surface[nSurface].pSurface->SetColorKey(DDCKEY_SRCBLT, &colKey))	return true;
	return false;
}

bool CDXDDraw::SurfaceRelease(long nSurface)
{
	m_Surface[nSurface].Release();
	return true;
}

void CDXDDraw::SurfaceToBack(long nSurface, long x, long y, RECT rt)
{
	if(!m_Surface[nSurface].pSurface)
	{
		char str[256];
		wsprintf(str, "%d surface 값이 널입니다.", nSurface);
		AfxErrMsg(str);
		return;
	}

	// 클리핑 처리...
	if(x<0)
	{
		rt.left+=abs(x);	x=0;
	}

	if(y<0)
	{
		rt.top+= abs(y);	y=0;
	}

	if(x+RT_WIDTH(rt)>=m_MaxScrSz.cx)	rt.right-=x+RT_WIDTH(rt)-m_MaxScrSz.cx;
	if(y+RT_HEIGHT(rt)>=m_MaxScrSz.cy)	rt.bottom-=y+RT_HEIGHT(rt)-m_MaxScrSz.cy;

	if(DDERR_SURFACELOST==m_pDDSBack->BltFast(x, y, m_Surface[nSurface].pSurface, &rt, DDBLTFAST_WAIT))
		RestoreAll();
}

void CDXDDraw::SurfaceToBackTrans(long nSurface, long x, long y, RECT rt)
{
	if(!m_Surface[nSurface].pSurface)
	{
		char str[256];
		wsprintf(str, "%d surface 값이 널입니다.", nSurface);
		AfxErrMsg(str);
		return;
	}

	// 클리핑 처리...
	if(x<0)
	{
		rt.left+=abs(x);	x=0;
	}

	if(y<0)
	{
		rt.top+= abs(y);	y=0;
	}

	if(x+RT_WIDTH(rt)>=m_MaxScrSz.cx)	rt.right-=x+RT_WIDTH(rt)-m_MaxScrSz.cx;
	if(y+RT_HEIGHT(rt)>=m_MaxScrSz.cy)	rt.bottom-=y+RT_HEIGHT(rt)-m_MaxScrSz.cy;

	if(DDERR_SURFACELOST==m_pDDSBack->BltFast(x, y, m_Surface[nSurface].pSurface, &rt, DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY))
		RestoreAll();
}

void CDXDDraw::SurfaceToSurface(long nSource, long nTarget, long x, long y, RECT rt)
{
	// 클리핑 처리...
	if(x<0)
	{
		rt.left+=abs(x);	x=0;
	}

	if(y < 0)
	{
		rt.top+= abs(y);	y=0;
	}

	if(x+RT_WIDTH(rt)>=m_Surface[nTarget].Width)	rt.right-=x+RT_WIDTH(rt)-m_Surface[nTarget].Width;
	if(y+RT_HEIGHT(rt)>=m_Surface[nTarget].Height)	rt.bottom-=y+RT_HEIGHT(rt)-m_Surface[nTarget].Height;

	if(DDERR_SURFACELOST==m_Surface[nTarget].pSurface->BltFast(x, y, m_Surface[nSource].pSurface, &rt, DDBLTFAST_WAIT))
	{
		RestoreAll();
	}
}

HRESULT	CDXDDraw::Blt(long nSource, RECT rtSource, long nTarget, RECT rtTarget)
{
	return (m_Surface[nTarget].pSurface->Blt(&rtTarget, m_Surface[nSource].pSurface, &rtSource, DDBLT_WAIT, NULL));
}

void CDXDDraw::RestoreAll()
{
	if(DD_OK!=m_pDDSPrimary->Restore())		AfxErrMsg("프라이머리 화면 복구실패.");
	if(DD_OK!=m_pDDSBack->Restore())		AfxErrMsg("프라이머리 화면 복구실패.");
	
	for(long i=0;i<SURFACE_MAX_NUM;i++)
	{
		if(m_Surface[i].pSurface)
		{
			m_Surface[i].pSurface->Restore();
			if(strlen(m_Surface[i].FileName)>0)
			{
				BmpReload(m_Surface[i].pSurface, m_Surface[i].FileName);
			}
		}
	}
}

void CDXDDraw::DrawOn(BOOL drawOn)
{
	m_bDrawOn=drawOn;
}


void CDXDDraw::FpsShow()
{
	++m_FrmCur;
	m_TimeCur=GetTickCount();

	if((m_TimeCur-m_TimeOld)>1000)
	{
		m_Fps=m_FrmCur;
		m_FrmCur=0;
		m_TimeOld=m_TimeCur;
	}
	wsprintf(m_TimeStr,"Frm=%03d, Fps=%03d", m_FrmCur, m_Fps);
	PutCheckString(500, 1, m_TimeStr);
}

long CDXDDraw::PixelFormatCheck()
{
	ZeroMemory(&m_DDPixelFormat, sizeof(m_DDPixelFormat));
	m_DDPixelFormat.dwSize = sizeof(m_DDPixelFormat);
	
	if( m_pDDSPrimary == NULL )
		return FALSE;

	m_pDDSPrimary -> GetPixelFormat(&m_DDPixelFormat);

	if(m_DDPixelFormat.dwFlags&DDPF_RGB)
	{
		return m_DDPixelFormat.dwRGBBitCount;
	}
	else if(m_DDPixelFormat.dwFlags&DDPF_PALETTEINDEXED8)
	{
		return 8;
	}
	else
	{
		AfxErrMsg("적합한 디스플레이의 픽셀 포맷이 없습니다.");
		return 0;
	}
}


LPDIRECTDRAWSURFACE7 CDXDDraw::BmpLoad(LPCSTR szBitmap, long dx, long dy)
{
    HBITMAP                 hbm;
    BITMAP                  bm;
    DDSURFACEDESC2          ddsd;
    LPDIRECTDRAWSURFACE7    pdds;


    hbm = (HBITMAP) LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, dx, dy, LR_CREATEDIBSECTION);
    if(hbm==NULL)   hbm=(HBITMAP) LoadImage(NULL, szBitmap, IMAGE_BITMAP, dx, dy, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
    if(hbm==NULL)	hbm=(HBITMAP) LoadImage(NULL, szBitmap, IMAGE_BITMAP, dx, dy, LR_CREATEDIBSECTION);
   // if(hbm==NULL)	hbm=(HBITMAP) LoadImage(g_InstDll, szBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
	if(hbm==NULL)	return NULL;
    GetObject(hbm, sizeof(bm), &bm);
    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize=sizeof(ddsd);
    ddsd.dwFlags=DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
    ddsd.dwWidth=bm.bmWidth;
    ddsd.dwHeight = bm.bmHeight;
    if(DD_OK!=m_pDDraw->CreateSurface(&ddsd, &pdds, NULL))  return NULL;
    BmpToSurface(pdds, hbm, 0, 0, 0, 0);
    DeleteObject(hbm);
    return pdds;
}

HRESULT CDXDDraw::BmpReload(LPDIRECTDRAWSURFACE7 pdds, LPCSTR szBitmap)
{
    HBITMAP                 hbm;
    HRESULT                 hr;

    //
    //  Try to load the bitmap as a resource, if that fails, try it as a file
    //
    hbm=(HBITMAP)	LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
    if(hbm==NULL)	hbm=(HBITMAP) LoadImage(NULL, szBitmap, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
	//if(hbm==NULL)	hbm=(HBITMAP)LoadImage(g_InstDll, szBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
	//if(hbm==NULL)	hbm=(HBITMAP)LoadImage(g_InstDll, szBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
	//if(hbm==NULL)	hbm=LoadBitmap(g_InstDll, MAKEINTRESOURCE(1));

    if(hbm==NULL)
	{
		char str[256];
		wsprintf(str, "%s file load failed", szBitmap);
		AfxErrMsg(str);
        return E_FAIL;
    }
    hr=BmpToSurface(pdds, hbm, 0, 0, 0, 0);
    if(hr!=DD_OK)
    {
		char str[256];
		wsprintf(str, "%s file load failed", szBitmap);
		AfxErrMsg(str);
    }
    DeleteObject(hbm);
    return hr;
}

SIZE CDXDDraw::BmpSizeGet(char *pFileName)
{
	SIZE sz={0,0};

	HANDLE	hFile;
	
	BITMAPFILEHEADER  bmpFileHeader;
	BITMAPINFOHEADER  bmpInfoHeader;
	DWORD nRead;
	hFile = CreateFile(pFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
	if(hFile == INVALID_HANDLE_VALUE)	return sz;
	
	if((NULL==ReadFile(hFile, &bmpFileHeader, sizeof(BITMAPFILEHEADER), &nRead, NULL))||
	   (NULL==ReadFile(hFile, &bmpInfoHeader, sizeof(BITMAPINFOHEADER), &nRead, NULL))||
	   (bmpFileHeader.bfType!=*(WORD *) "BM"))
	{
		char str[256];
		wsprintf(str, "%s 파일 열기 실패.", pFileName);
		AfxErrMsg(str);
		CloseHandle(hFile);
		return sz;
	}
	CloseHandle(hFile);
	sz.cx=bmpInfoHeader.biWidth;
	sz.cy=bmpInfoHeader.biHeight;
	return sz;
}



//-----------------------------------------------------------------------------
// Name: DDCopyBitmap()
// Desc: Draw a bitmap into a DirectDrawSurface
//-----------------------------------------------------------------------------
HRESULT CDXDDraw::BmpToSurface(LPDIRECTDRAWSURFACE7 pdds, HBITMAP hbm, long x, long y, long dx, long dy)
{
    HDC                     hdcImage;
    HDC                     hdc;
    BITMAP                  bm;
    DDSURFACEDESC2          ddsd;
    HRESULT                 hr;

    if (hbm == NULL || pdds == NULL)
        return E_FAIL;
    //
    // Make sure this surface is restored.
    //
    pdds->Restore();
    //
    // Select bitmap longo a memoryDC so we can use it.
    //
    hdcImage = CreateCompatibleDC(NULL);
    if (!hdcImage)
        OutputDebugString("createcompatible dc failed\n");
    SelectObject(hdcImage, hbm);
    //
    // Get size of the bitmap
    //
    GetObject(hbm, sizeof(bm), &bm);
    dx = dx == 0 ? bm.bmWidth : dx;     // Use the passed size, unless zero
    dy = dy == 0 ? bm.bmHeight : dy;
    //
    // Get size of surface.
    //
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
    pdds->GetSurfaceDesc(&ddsd);

    if ((hr = pdds->GetDC(&hdc)) == DD_OK)
    {
        StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, x, y,
                   dx, dy, SRCCOPY);
        pdds->ReleaseDC(hdc);
    }
    DeleteDC(hdcImage);
    return hr;
}

void CDXDDraw::Rect(RECT rt, COLORREF col, bool fillOn)
{
	if(fillOn)	FillColor(rt, col);
	else
	{
		RGB_SET(m_BitPerPixel, col);	// 칼라 셋팅...
		RECT drawRt;
		DDBLTFX		ddbltfx;
		ddbltfx.dwSize=sizeof(ddbltfx);
		ddbltfx.dwFillColor=col;
		
		if((rt.right>0)&&(rt.left<m_MaxScrRt.right))
		if(((rt.top>=0)&&(rt.top<m_MaxScrRt.bottom))||((rt.bottom>0)&&(rt.bottom<=m_MaxScrRt.bottom)))
		{
			(rt.left<0)?drawRt.left=0:drawRt.left=rt.left;
			(rt.right>m_MaxScrRt.right)?drawRt.right=m_MaxScrRt.right:drawRt.right=rt.right;

			// 윗줄 긋기...........
			if((rt.top>=0)&&(rt.top<m_MaxScrRt.bottom))
			{
				drawRt.top=rt.top;
				drawRt.bottom=rt.top+1;
				m_pDDSBack->Blt(&drawRt, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
			}

			// 밑줄 긋기......
			if((rt.bottom>0)&&(rt.bottom<=m_MaxScrRt.bottom))
			{
				drawRt.top=rt.bottom;
				drawRt.bottom=rt.bottom+1;
				m_pDDSBack->Blt(&drawRt, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
			}	
		}

		if((rt.bottom>0)&&(rt.top<m_MaxScrRt.bottom))
		if(((rt.left>=0)&&(rt.left<m_MaxScrRt.right))||((rt.right>0)&&(rt.right<=m_MaxScrRt.right)))
		{
			(rt.top<0)?drawRt.top=0:drawRt.top=rt.top;
			(rt.bottom>m_MaxScrRt.bottom)?drawRt.bottom=m_MaxScrRt.bottom:drawRt.bottom=rt.bottom;

			// 왼쪽 줄 긋기
			if((rt.left>=0)&&(rt.left<m_MaxScrRt.right))
			{
				drawRt.left=rt.left;
				drawRt.right=rt.left+1;
				m_pDDSBack->Blt(&drawRt, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
			}

			// 오른쪽 줄 긋기
			if((rt.right>0)&&(rt.right<=m_MaxScrRt.right))
			{
				drawRt.left=rt.right;
				drawRt.right=rt.right+1;
				m_pDDSBack->Blt(&drawRt, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
			}
		}
	}
}

void CDXDDraw::FillColor(RECT rt, COLORREF col)
{
	RGB_SET(m_BitPerPixel, col);		// 칼라 셋팅......
	DDBLTFX		ddbltfx;
	ddbltfx.dwSize=sizeof(ddbltfx);
	ddbltfx.dwFillColor=col;

	if(rt.left<0)	rt.left=0;
	if(rt.top<0)	rt.top=0;
	if(rt.right>m_MaxScrRt.right)	rt.right=m_MaxScrRt.right;
	if(rt.bottom>m_MaxScrRt.bottom) rt.bottom=m_MaxScrRt.bottom;

	m_pDDSBack->Blt(&rt, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx );
}


// 8비트 bmp를 bmp16(5:5:5)모드로 바꿔줌.

/*
bool CDXDDraw::Bmp08ToBmp16(char * pFileName, BYTE *pBmp)
{
	BYTE *ptempBmp=pBmp;				// 임시 원본 비트맵 포인터.
	BITMAPFILEHEADER tempBmpFileHeader;	// 임시 파일헤더.
	BITMAPINFOHEADER tempBmpInfoHeader;	// 임시 인포헤더.
	RGBQUAD tempPal[256];				// 임시 팔레트.

	// 그림의 헤더 정보 넣기...
	memcpy(&tempBmpFileHeader, ptempBmp,sizeof(tempBmpFileHeader));	
	memcpy(&tempBmpInfoHeader, ptempBmp+sizeof(tempBmpFileHeader), sizeof(tempBmpInfoHeader));
	memcpy(&tempPal, ptempBmp+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER), sizeof(tempPal));

	long tempWidth=tempBmpInfoHeader.biWidth;	// 넓이..
	long tempHeight=tempBmpInfoHeader.biHeight;	// 높이..
	DWORD temp08LineBytes=((tempWidth)+3)&~3;
	DWORD temp16LineBytes=((tempWidth*2)+3)&~3;	// 4의 배수화 시킴...
	DWORD tempImageBytes=temp16LineBytes*tempHeight;
	DWORD tempFileSize=sizeof(tempBmpFileHeader)+sizeof(tempBmpInfoHeader)+tempImageBytes;

	// 파일 헤더 내용 바꾸기...
	tempBmpFileHeader.bfOffBits=sizeof(tempBmpFileHeader)+sizeof(tempBmpInfoHeader);
	tempBmpFileHeader.bfSize=tempFileSize;

	// 인포 헤더 내용 바꾸기.
	tempBmpInfoHeader.biBitCount=16;
	tempBmpInfoHeader.biClrUsed=0;
	tempBmpInfoHeader.biClrImportant=0;
	tempBmpInfoHeader.biCompression=BI_RGB;
	tempBmpInfoHeader.biSizeImage=0;

	// 각각의 이미지 비트.
	BYTE	*ptemp08ImgByte=ptempBmp+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(tempPal);
	USHORT	*ptemp16ImgByte=(USHORT*)malloc(tempImageBytes);
	ZeroMemory(ptemp16ImgByte, temp16LineBytes*tempHeight);

	BYTE *ptempCur08=ptemp08ImgByte;
	USHORT *ptempCur16=ptemp16ImgByte;
	long tempY=0, tempX=0;

	RGBQUAD tempCurPal;

	
	for(tempY=0;tempY<tempHeight;tempY++)
	{
		ptempCur08=ptemp08ImgByte+(temp08LineBytes*tempY);
		ptempCur16=ptemp16ImgByte+((temp16LineBytes*tempY)>>1);

		for(tempX=0;tempX<tempWidth;tempX++)
		{
			tempCurPal=tempPal[*ptempCur08];
			
			// 565 모드로 만들어줌...
			
//			*ptempCur16=(
//						((tempCurPal.rgbRed<<8)&0xF800)|
//						((tempCurPal.rgbGreen<<3)&0x07E0)|
//						(tempCurPal.rgbBlue>>3&0x001F));

			// 555 모드...
			*ptempCur16=(
						((tempCurPal.rgbRed<<7)&0x7C00)|
						((tempCurPal.rgbGreen<<2)&0x03E0)|
						(tempCurPal.rgbBlue>>3&0x001F));

			++ptempCur16;
			++ptempCur08;
		}
	}

	char tempStr[256]={NULL,};
	long tempStrLen=strlen(pFileName);
	if(pFileName)
	{
		for(long i=0;i<tempStrLen;i++)
		{
			if(pFileName[i]=='.')		
				break;
			else
				tempStr[i]=pFileName[i];
		}
	}
	char tempFileName[256]={NULL,};
	sprintf(tempFileName, "%s16.bmp", tempStr);

	FILE * ptempFile=fopen(tempFileName,"wb");
	if(!ptempFile)
	{
		char tempStr[64]={NULL,};
		sprintf(tempStr,"%s 열기 실패..\n", tempFileName);
		AfxErrMsg(tempStr);
		return FALSE;
	}
	long tempRet=0;

	tempRet=fwrite(&tempBmpFileHeader, 1, sizeof(tempBmpFileHeader), ptempFile);
	tempRet=fwrite(&tempBmpInfoHeader, 1, sizeof(tempBmpInfoHeader), ptempFile);
	tempRet=fwrite(ptemp16ImgByte, 1, tempImageBytes, ptempFile);
	if(ptempFile)	fclose(ptempFile);
	if(ptemp16ImgByte)	free(ptemp16ImgByte);
	ptemp16ImgByte=NULL;

	return true;
}

bool CDXDDraw::Bmp24ToBmp16(char * pFileName, BYTE *pBmp)
{
	BYTE *ptempBmp=pBmp;				// 임시 원본 비트맵 포인터.
	BITMAPFILEHEADER tempBmpFileHeader;	// 임시 파일헤더.
	BITMAPINFOHEADER tempBmpInfoHeader;	// 임시 인포헤더.

	// 그림의 헤더 정보 넣기...
	memcpy(&tempBmpFileHeader, ptempBmp,sizeof(tempBmpFileHeader));	
	memcpy(&tempBmpInfoHeader, ptempBmp+sizeof(tempBmpFileHeader), sizeof(tempBmpInfoHeader));

	long tempWidth=tempBmpInfoHeader.biWidth;	// 넓이..
	long tempHeight=tempBmpInfoHeader.biHeight;	// 높이..
	DWORD temp24LineBytes=((tempWidth*3)+3)&~3;
	DWORD temp16LineBytes=((tempWidth*2)+3)&~3;	// 4의 배수화 시킴...
	DWORD tempImageBytes=temp16LineBytes*tempHeight;
	DWORD tempFileSize=sizeof(tempBmpFileHeader)+sizeof(tempBmpInfoHeader)+tempImageBytes;

	// 파일 헤더 내용 바꾸기...
	tempBmpFileHeader.bfOffBits=sizeof(tempBmpFileHeader)+sizeof(tempBmpInfoHeader);
	tempBmpFileHeader.bfSize=tempFileSize;

	// 인포 헤더 내용 바꾸기.
	tempBmpInfoHeader.biBitCount=16;
	tempBmpInfoHeader.biClrUsed=0;
	tempBmpInfoHeader.biClrImportant=0;
	tempBmpInfoHeader.biCompression=BI_RGB;
	tempBmpInfoHeader.biSizeImage=0;

	// 각각의 이미지 비트.
	BYTE	*ptemp24ImgByte=ptempBmp+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
	USHORT	*ptemp16ImgByte=(USHORT*)malloc(tempImageBytes);
	ZeroMemory(ptemp16ImgByte, temp16LineBytes*tempHeight);

	BYTE *ptempCur24=ptemp24ImgByte;
	USHORT *ptempCur16=ptemp16ImgByte;
	long tempY=0, tempX=0;
	BYTE r=0,g=0,b=0;
	
	
	for(tempY=0;tempY<tempHeight;tempY++)
	{
		ptempCur24=ptemp24ImgByte+(temp24LineBytes*tempY);
		ptempCur16=ptemp16ImgByte+((temp16LineBytes*tempY)>>1);

		for(tempX=0;tempX<tempWidth;tempX++)
		{
			b=*(ptempCur24);
			g=*(ptempCur24+1);
			r=*(ptempCur24+2);

			// 565 모드로 만들어줌...
			
			//*ptempCur16=(
			//			((tempCurPal.rgbRed<<8)&0xF800)|
			//			((tempCurPal.rgbGreen<<3)&0x07E0)|
			//			(tempCurPal.rgbBlue>>3&0x001F));

			// 555 모드...
			*ptempCur16=(
						((r<<7)&0x7C00)|
						((g<<2)&0x03E0)|
						((b>>3)&0x001F));

			++ptempCur16;
			ptempCur24+=3;
		}
	}

	char tempStr[256]={NULL,};
	long tempStrLen=strlen(pFileName);
	if(pFileName)
	{
		for(long i=0;i<tempStrLen;i++)
		{
			if(pFileName[i]=='.')		
				break;
			else
				tempStr[i]=pFileName[i];
		}
	}
	char tempFileName[256]={NULL,};
	sprintf(tempFileName, "%s16.bmp", tempStr);

	FILE * ptempFile=fopen(tempFileName,"wb");
	if(!ptempFile)
	{
		char tempStr[64]={NULL,};
		sprintf(tempStr,"%s 열기 실패..\n", tempFileName);
		AfxErrMsg(tempStr);
		return FALSE;
	}
	long tempRet=0;

	tempRet=fwrite(&tempBmpFileHeader, 1, sizeof(tempBmpFileHeader), ptempFile);
	tempRet=fwrite(&tempBmpInfoHeader, 1, sizeof(tempBmpInfoHeader), ptempFile);
	tempRet=fwrite(ptemp16ImgByte, 1, tempImageBytes, ptempFile);
	if(ptempFile)	fclose(ptempFile);
	if(ptemp16ImgByte)	free(ptemp16ImgByte);
	ptemp16ImgByte=NULL;

	return true;
}



BYTE * CDXDDraw::BmpLoad(char * pstrFileName)
{
	HDC tempHdc = NULL;
	HANDLE	hFile;
	DWORD dwFileSize, dwHighSize, dwBytesRead;

	char tempStr[255]={NULL,};

	BYTE * ptempBmp=NULL;
	BITMAPFILEHEADER * ptempBmpFileHeader=NULL;

	long tempBmpWidth=0;
	long tempBmpHeight=0;
	long tempBitPerPixel=0;

	BOOL bSuccess = FALSE;
	
	hFile = CreateFile( pstrFileName, 
		                GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
						FILE_FLAG_SEQUENTIAL_SCAN, NULL);

	if(hFile == INVALID_HANDLE_VALUE)
		return NULL;

	dwFileSize = GetFileSize(hFile, &dwHighSize);
	if(dwHighSize)
	{
		CloseHandle(hFile);
		return NULL;
	}

	ptempBmp=(BYTE *) malloc(dwFileSize);
	if(!ptempBmp)
	{
		CloseHandle(hFile);
		return NULL;
	}
	ZeroMemory(ptempBmp, dwFileSize);
	
	ptempBmpFileHeader=(BITMAPFILEHEADER *)ptempBmp;
	bSuccess = ReadFile(hFile, ptempBmp, dwFileSize, &dwBytesRead, NULL);
	CloseHandle(hFile);

	if(!bSuccess || (dwBytesRead != dwFileSize)
				 || (ptempBmpFileHeader->bfType != *(WORD *) "BM"))
	{
		OutputDebugString("그림 그리기 실패....!!");
		MAL_FREE(ptempBmp);
		return NULL;
	}
	else 
		return ptempBmp;
}
*/