www.pudn.com > GameEngine_src.rar > CEasyDraw.cpp


#include "CEasyDraw.h" 
#include "normal.h" 
#include "BaseUtil.h" 
//#include "ijl.h" 
#include  
#include  
#include  
#include  
#include  
#include  
 
 
#pragma comment( lib, "ddraw.lib" ) 
#pragma comment( lib, "dxguid.lib" ) 
//#pragma comment( lib, "ijl15l.lib" ) 
 
 
 
 
CEasyDraw theEasyDraw; 
const int MAX_NUM_SURF = 1024; 
int CEasyDraw::g_CharWidth; 
int CEasyDraw::g_CharHeight; 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
CEasyDraw::CEasyDraw() 
{ 
	m_lpDD			= NULL; 
	m_lpDDSBack		= NULL; 
	m_lpDDSPrimary	= NULL; 
 
	m_hWnd			= NULL; 
	 
	m_DisplayFormat = R5G6B5; 
	m_iWidth = 800; 
	m_iHeight = 600; 
 
	m_lpGammaControl = NULL; 
	m_pGammaData	 = NULL; 
} 
 
CEasyDraw::~CEasyDraw() 
{ 
 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CEasyDraw::Init( HWND hwnd, bool isWindowed, int iW, int iH ) 
{ 
	Free(); 
	HRESULT hr; 
 
	//创建lpdd7对象: 
	hr = DirectDrawCreateEx(NULL, (void **)&m_lpDD, IID_IDirectDraw7, NULL);  
	if ( hr != DD_OK ) 
	{ 
		Warn( "创建DirectDraw7接口失败!" ); 
		return false; 
	} 
 
	if ( !isWindowed ) 
	{ 
		SetWindowLong( hwnd, GWL_STYLE, WS_POPUP ); 
 
		hr = m_lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); 
		if ( hr != DD_OK ) 
		{ 
			return false; 
		} 
 
		//设置屏幕模式: 
		hr = m_lpDD->SetDisplayMode( iW, iH, 16, 0, 0 );				//只支持16位模式 
		if ( hr != DD_OK ) 
		{ 
			return false; 
		} 
		 
		//创建主页面: 
		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; 
		 
		hr = m_lpDD->CreateSurface(&ddsd, &m_lpDDSPrimary, NULL); 
		if ( hr != DD_OK ) 
		{ 
			return false; 
		} 
		 
		//创建后台页面: 
		DDSCAPS2 ddscaps; 
		ZeroMemory( &ddscaps, sizeof( ddscaps ) ); 
		ddscaps.dwCaps = DDSCAPS_BACKBUFFER; 
		hr = m_lpDDSPrimary->GetAttachedSurface( &ddscaps, &m_lpDDSBack ); 
		if ( hr != DD_OK ) 
		{ 
			return false; 
		} 
 
		m_bWindowed = false; 
	} 
	else 
	{ 
		hr = m_lpDD->SetCooperativeLevel(hwnd, DDSCL_NORMAL); 
		if ( hr != DD_OK ) 
		{ 
			return false; 
		} 
 
		RECT  rcWork; 
		RECT  rc; 
		DWORD dwStyle; 
		 
		// If we are still a WS_POPUP window we should convert to a normal app 
		// window so we look like a windows app. 
		dwStyle  = GetWindowStyle( hwnd ); 
		dwStyle &= ~WS_POPUP; 
		dwStyle &= ~WS_SIZEBOX; 
		dwStyle &= ~WS_THICKFRAME; 
		dwStyle &= ~WS_MAXIMIZE; 
		dwStyle &= ~WS_MAXIMIZEBOX; 
		dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX;// | WS_SYSMENU; 
		SetWindowLong( hwnd, GWL_STYLE, dwStyle ); 
		 
		// Aet window size 
		SetRect( &rc, 0, 0, iW, iH ); 
		 
		AdjustWindowRectEx( &rc, GetWindowStyle(hwnd), GetMenu(hwnd) != NULL, 
							GetWindowExStyle(hwnd) ); 
		 
		SetWindowPos( hwnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, 
			SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); 
		 
		SetWindowPos( hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, 
			SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); 
		 
		//  Make sure our window does not hang outside of the work area 
		SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); 
		GetWindowRect( hwnd, &rc ); 
		if( rc.left < rcWork.left ) rc.left = rcWork.left; 
		if( rc.top  < rcWork.top )  rc.top  = rcWork.top; 
		SetWindowPos( hwnd, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); 
		 
		LPDIRECTDRAWCLIPPER pcClipper; 
		 
		// Create the primary surface 
		DDSURFACEDESC2 ddsd; 
		ZeroMemory( &ddsd, sizeof( ddsd ) ); 
		ddsd.dwSize         = sizeof( ddsd ); 
		ddsd.dwFlags        = DDSD_CAPS; 
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 
		 
		if( FAILED( m_lpDD->CreateSurface( &ddsd, &m_lpDDSPrimary, NULL ) ) ) 
			return false; 
		 
		// Create the backbuffer surface 
		ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;     
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; 
		ddsd.dwWidth        = iW; 
		ddsd.dwHeight       = iH; 
		 
		if( FAILED( hr = m_lpDD->CreateSurface( &ddsd, &m_lpDDSBack, NULL ) ) ) 
			return false; 
		 
		if( FAILED( hr = m_lpDD->CreateClipper( 0, &pcClipper, NULL ) ) ) 
			return false; 
		 
		if( FAILED( hr = pcClipper->SetHWnd( 0, hwnd ) ) ) 
		{ 
			pcClipper->Release(); 
			Warn( "设置裁剪器失败!" ); 
			return false; 
		} 
		 
		if( FAILED( hr = m_lpDDSPrimary->SetClipper( pcClipper ) ) ) 
		{ 
			pcClipper->Release(); 
			return false; 
		} 
		 
		// Done with clipper 
		pcClipper->Release(); 
		m_bWindowed = true; 
	} 
 
	m_hWnd = hwnd; 
	UpdateRect(); 
 
	//创建特效页面: 
	hr = CreateSurfaceHelp( m_lpDD, &m_lpDDSTemp, iW, iH, true, false, 0 ); 
	if ( hr != DD_OK ) 
	{ 
		return false; 
	} 
 
	//检测显示模式: 
	DDPIXELFORMAT ddpf; 
	ddpf.dwSize = sizeof( DDPIXELFORMAT ); 
	hr = m_lpDDSPrimary->GetPixelFormat( &ddpf ); 
	if ( hr != DD_OK ) 
	{ 
		return false; 
	} 
	 
	if ( ddpf.dwRGBBitCount != 16 ) 
	{ 
		if ( Ask( "当前显示模式不是16位,将切换到全屏模式,是否继续" ) ) 
		{ 
			Init( hwnd, false, iW, iH ); 
		} 
		else 
		{ 
			return false; 
		} 
	} 
 
	if ( ddpf.dwRBitMask  == 0xf800 ) 
	{ 
		m_DisplayFormat = R5G6B5;					//565模式 
	} 
	else if ( ddpf.dwRBitMask  == 0x7c00 ) 
	{ 
		m_DisplayFormat = R5G5B5;					//555模式 
	} 
 
	m_iWidth = iW; 
	m_iHeight= iH; 
 
	//获得GAMMA接口 
	hr = m_lpDDSPrimary->QueryInterface( IID_IDirectDrawGammaControl, (LPVOID *) &m_lpGammaControl ); 
	if ( hr != DD_OK ) 
	{ 
		return false; 
	} 
 
	m_pGammaData = new DDGAMMARAMP; 
	if ( m_pGammaData == NULL ) 
		return false; 
 
	//获取字符的宽,高 
	HDC hdc; 
	HFONT hFont; 
	if ( m_lpDDSBack->GetDC( &hdc ) != DD_OK ) 
		return false; 
	hFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT); 
	if ( hFont == NULL ) 
		return false; 
	SelectObject(hdc, hFont); 
	TEXTMETRIC tm; 
	GetTextMetrics(hdc, &tm); 
	g_CharWidth = tm.tmAveCharWidth; 
	g_CharHeight= tm.tmHeight + tm.tmExternalLeading + 2;  
	m_lpDDSBack->ReleaseDC(hdc); 
 
	bool ismmx = false; 
	_asm 
	{ 
		mov eax, 1; 
		cpuid; 
		test edx,00800000h; 
		jz _no; 
		mov ismmx, 1; 
_no: 
	} 
	m_IsMMX = ismmx; 
 
	return true; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CEasyDraw::Free() 
{ 
	if ( m_lpDD != NULL ) 
	{ 
		SafeRelease( m_lpGammaControl ); 
		SafeDelete( m_pGammaData ); 
 
		m_SurfaceList.Clear(); 
 
		SafeRelease( m_lpDDSTemp ); 
		SafeRelease( m_lpDDSBack ); 
		SafeRelease( m_lpDDSPrimary ); 
 
		m_lpDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); 
 
		m_lpDD->Release(); 
		m_lpDD = NULL; 
		m_hWnd = NULL; 
	} 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
CSurface * CEasyDraw::NewSurface() 
{ 
	CSurface *surf = m_SurfaceList.CreateOneNode(); 
	if ( surf != NULL ) 
		surf->Init(); 
	return surf; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CEasyDraw::DeleteSurface( CSurface *pSurf ) 
{ 
	if ( pSurf != NULL ) 
	{ 
		m_SurfaceList.Delete( pSurf ); 
	} 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CEasyDraw::IsLost() 
{ 
	bool isLost = false; 
 
	if ( m_lpDDSPrimary->IsLost() == DDERR_SURFACELOST ) 
	{ 
		isLost = true; 
		m_lpDDSPrimary->Restore(); 
		DDSURFACEDESC2 ddsd; 
		ddsd.dwSize = sizeof( DDSURFACEDESC2 ); 
 
		if ( m_lpDDSPrimary->GetSurfaceDesc( &ddsd ) == DD_OK ) 
		{ 
			m_iWidth = ddsd.dwWidth; 
			m_iHeight = ddsd.dwHeight; 
		} 
	} 
	if ( m_lpDDSBack->IsLost() == DDERR_SURFACELOST ) 
	{ 
		isLost = true; 
		m_lpDDSBack->Restore(); 
	} 
 
	if ( isLost ) 
	{ 
		CList::Iterator it; 
		for ( it = m_SurfaceList.Begin(); it != m_SurfaceList.End(); ++it ) 
			(*it).Restore(); 
	} 
 
	return isLost; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CEasyDraw::Present() 
{ 
    HRESULT hr; 
 
    if( NULL == m_lpDDSPrimary && NULL == m_lpDDSBack ) 
        return false; 
 
	IsLost(); 
 
    if( m_bWindowed ) 
        hr = m_lpDDSPrimary->Blt( &m_rcWindow, m_lpDDSBack, NULL, 0, NULL ); 
		//hr = m_lpDDSPrimary->BltFast( 0, 0, m_lpDDSBack, NULL, DDBLTFAST_WAIT  ); 
    else 
        hr = m_lpDDSPrimary->Flip( NULL, 0 ); 
	 
	if ( hr != DD_OK ) 
		return false; 
	 
	return true; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CEasyDraw::UpdateRect() 
{ 
    if( m_bWindowed ) 
    { 
        GetClientRect( m_hWnd, &m_rcWindow ); 
        ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); 
        ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); 
    } 
    else 
    { 
        SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), 
                 GetSystemMetrics(SM_CYSCREEN) ); 
    } 
 
	m_iHeight = m_rcWindow.bottom - m_rcWindow.top; 
	m_iWidth = m_rcWindow.right - m_rcWindow.left; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CEasyDraw::SetDisplayRect( const RECT *pRect ) 
{ 
    if( m_bWindowed ) 
    { 
        //GetClientRect( m_hWnd, &m_rcWindow ); 
		SetRect( &m_rcWindow, pRect->left, pRect->top, pRect->right, pRect->bottom ); 
 
        ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); 
        ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); 
    } 
    else 
    { 
        SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), 
                 GetSystemMetrics(SM_CYSCREEN) ); 
    } 
 
	m_iHeight = m_rcWindow.bottom - m_rcWindow.top; 
	m_iWidth = m_rcWindow.right - m_rcWindow.left; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CEasyDraw::Clear( DWORD color ) 
{ 
	ClearSurfaceHelp( m_lpDDSBack, NULL, color ); 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CEasyDraw::LightenessControl( int iAdd ) 
{ 
	assert( m_lpGammaControl != NULL && m_pGammaData != NULL ); 
	 
	m_lpGammaControl->GetGammaRamp( 0, m_pGammaData );	//获取GAMMA 
 
	int r = m_pGammaData->red[1] - m_pGammaData->red[0] + iAdd; 
	int g = m_pGammaData->green[1] - m_pGammaData->green[0] + iAdd; 
	int b = m_pGammaData->blue[1] - m_pGammaData->blue[0] + iAdd; 
 
	if ( r < 0 )	r = 0; 
	if ( g < 0 )	g = 0; 
	if ( b < 0 )	b = 0; 
 
	if ( r > 255 ) r = 255; 
	if ( g > 255 ) g = 255; 
	if ( b > 255 ) b = 255; 
 
	for ( int i = 1; i < 256; ++i ) 
	{ 
		m_pGammaData->red[i] = m_pGammaData->red[i-1] + r; 
		m_pGammaData->green[i] = m_pGammaData->green[i-1] + g; 
		m_pGammaData->blue[i] = m_pGammaData->blue[i-1] + b; 
	} 
 
	m_lpGammaControl->SetGammaRamp( 0, m_pGammaData ); 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CEasyDraw::ScreenShot( char *szDirectory ) 
{ 
	char sz[128]; 
	ZeroMemory( sz, 128 ); 
	if ( szDirectory != NULL ) 
	{ 
		strcpy( sz, szDirectory ); 
	} 
 
	strcat( sz, "ScreenShot%d.bmp" ); 
	 
	FILE *fp; 
	int i = 0; 
	char buf[128]; 
 
	wsprintf( buf, sz, i ); 
 
	while ( ( fp = fopen(buf, "rb") ) != NULL && i < 255 ) 
	{ 
		fclose(fp); 
		wsprintf( buf, sz, i ); 
		++i; 
	} 
 
	return CopySurfaceToBmp16( m_lpDDSBack, buf, NULL, Is565() );; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
DWORD CEasyDraw::ChangeColorKey( DWORD colorkey ) 
{ 
	DWORD w = colorkey; 
 
	if ( !Is565() ) 
	{ 
		return CHANGE_565_TO_555( w ); 
	} 
 
	return w; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
CSurface * CEasyDraw::CreateSurfaceEx(  char *szFileName, int iWidth, int iHeight, bool isSysMemory,  
										bool isColorKey, DWORD ColorKey ) 
{ 
	CSurface *surf = NewSurface(); 
	if ( surf != NULL ) 
	{ 
		bool b; 
 
		ColorKey = ChangeColorKey( ColorKey ); 
		if ( szFileName != NULL ) 
		{ 
			b = surf->CreateImageSurface( szFileName, isSysMemory, isColorKey, ColorKey ); 
		} 
		else 
		{ 
			b = surf->CreateNullSurface( iWidth, iHeight, isSysMemory, isColorKey, ColorKey ); 
		} 
 
		if ( b == false ) 
		{ 
			DeleteSurface( surf ); 
			return NULL; 
		} 
	} 
 
	return surf; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
CSurface * CEasyDraw::CreateSurface( char *szFileName, bool isColorKey, DWORD ColorKey ) 
{ 
	return CreateSurfaceEx( szFileName, 0, 0, false, isColorKey, ColorKey ); 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
CSurface * CEasyDraw::CreateSurfaceFromMemory( BYTE *pData, enum FILE_TYPE FileType,  
											  bool isSysMemory, bool isColorKey, DWORD ColorKey ) 
{ 
	CSurface *surf = NewSurface(); 
	if ( surf != NULL ) 
	{ 
		bool b; 
 
		ColorKey = ChangeColorKey( ColorKey ); 
 
		switch ( FileType ) 
		{ 
		case FT_ECP: 
			b = ( surf->CreateEcpSurfaceFromMemory( pData, isSysMemory, 0 ) != 0 ); 
			break; 
		default: 
			b = false; 
			break; 
		} 
 
		if ( b == false ) 
		{ 
			debug_assert( false ); 
			DeleteSurface( surf ); 
			return NULL; 
		} 
	} 
	else 
		assert( false ); 
 
	return surf; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
CSurface * CEasyDraw::CreateSurfaceFromEPG( FILE *fp, int offset, POINT *pPoint ) 
{ 
 
	CSurface *surf = NewSurface(); 
	if ( surf != NULL ) 
	{ 
		if ( surf->CreateEcpSurfaceHelp( fp, offset, pPoint, false ) == false ) 
		{ 
			DeleteSurface( surf ); 
			return NULL; 
		} 
	} 
 
	return surf; 
} 
 
 
 
 
//-------------------------------------------------EasyDraw辅助函数------------------------------------------------------ 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
CEasyDraw * InitEasyDraw( HWND hwnd, bool isWindowed, int iW, int iH ) 
{ 
	if ( theEasyDraw.Init( hwnd, isWindowed, iW, iH ) == false ) 
	{ 
		return NULL; 
	} 
 
	return &theEasyDraw; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void FreeEasyDraw() 
{ 
	theEasyDraw.Free(); 
} 
 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
CEasyDraw *GetEasyDrawPointer() 
{ 
	return &theEasyDraw; 
} 
 
 
//-------------------------------------------------EasyDraw应用函数------------------------------------------------------ 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void ClearSurfaceHelp( LPDIRECTDRAWSURFACE7 lpDDSurface, RECT *pRect, DWORD Color ) 
{ 
	DDBLTFX ddbltfx;	 
 
	ddbltfx.dwSize = sizeof(ddbltfx);   
	ddbltfx.dwFillColor = Color; 
 
	lpDDSurface->Blt( pRect, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); 
} 
 
 
 
////////////////////////////////////////////////////////////////////// 
//创建一个离屏页面 
//参数:页面宽高,是否使用系统内存,是否有关键色 
////////////////////////////////////////////////////////////////////// 
HRESULT CreateSurfaceHelp( LPDIRECTDRAW7 lpdd, 
						   LPDIRECTDRAWSURFACE7 *ppSurface, 
						   int iW, int iH,  
						   bool isSysMemory, bool isColorKey,  
						   DWORD ColorKey ) 
{ 
	if ( ppSurface == NULL ) 
		return E_FAIL; 
 
	LPDIRECTDRAWSURFACE7 lpDDSurface = NULL; 
	DDSURFACEDESC2 ddsd; 
	ZeroMemory( &ddsd, sizeof(ddsd)); 
	ddsd.dwSize = sizeof(ddsd); 
	ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; 
 
	if ( isSysMemory ) 
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; 
	else 
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; 
 
	ddsd.dwWidth = iW; 
	ddsd.dwHeight = iH; 
 
	HRESULT hr; 
	hr = lpdd->CreateSurface( &ddsd, &lpDDSurface, NULL ); 
 
	if ( hr == DDERR_OUTOFVIDEOMEMORY )						//如果显存不足,将在内存中分配页面 
	{ 
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; 
		hr = lpdd->CreateSurface( &ddsd, &lpDDSurface, NULL ); 
 
		if ( hr != DD_OK ) 
			return hr; 
		else 
			hr = DDERR_OUTOFVIDEOMEMORY;					//如果在内存中分配成功,返回DDERR_OUTOFVIDEOMEMORY 
	} 
 
 
 
	//设置关键色 
	if ( isColorKey ) 
		SetColorKeyHelp( lpDDSurface, ColorKey ); 
	*ppSurface = lpDDSurface; 
	return hr; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void SetColorKeyHelp( LPDIRECTDRAWSURFACE7 lpDDSurface, DWORD ColorKey) 
{ 
	DDCOLORKEY ddck; 
	ddck.dwColorSpaceLowValue = ColorKey; 
	ddck.dwColorSpaceHighValue = ColorKey; 
	lpDDSurface->SetColorKey( DDCKEY_SRCBLT, &ddck ); 
} 
 
 
 
////////////////////////////////////////////////////////////////////// 
//将一个位图载入到一个页面中 
////////////////////////////////////////////////////////////////////// 
LPDIRECTDRAWSURFACE7 LoadBmpToSurface( char *szFileName, LPDIRECTDRAWSURFACE7 lpDDSurface, int x, int y, bool isFromFile ) 
{ 
	if ( lpDDSurface == NULL ) 
		return NULL; 
 
	HBITMAP hBmp; 
 
 
    //当一个资源 
	if ( isFromFile ) 
		hBmp = (HBITMAP)LoadImage( NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE ); 
	else 
		hBmp = (HBITMAP)LoadImage(GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); 
	 
	if ( hBmp == NULL ) 
		return NULL; 
	 
	return LoadBmpToSurfaceFromHBmp( hBmp, lpDDSurface, x, y ); 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
LPDIRECTDRAWSURFACE7 LoadBmpToSurfaceFromHBmp( HBITMAP hBmp,  
											   LPDIRECTDRAWSURFACE7 lpDDSurface,  
											   int x, int y ) 
{	 
 
    HDC            hDCImage; 
    HDC            hDC; 
    BITMAP         bmp; 
    DDSURFACEDESC2 ddsd; 
    HRESULT        hr; 
 
    if( hBmp == NULL || lpDDSurface == NULL ) 
        return NULL; 
 
    if( FAILED( hr = lpDDSurface->Restore() ) ) 
        return NULL; 
 
    ddsd.dwSize  = sizeof(ddsd); 
    lpDDSurface->GetSurfaceDesc( &ddsd ); 
 
    if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) 
        return NULL; 
 
    hDCImage = CreateCompatibleDC( NULL ); 
    if( NULL == hDCImage ) 
        return NULL; 
 
    SelectObject( hDCImage, hBmp ); 
 
    GetObject( hBmp, sizeof(bmp), &bmp ); 
  
    if( FAILED( hr = lpDDSurface->GetDC( &hDC ) ) ) 
        return NULL; 
 
	BitBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight, hDCImage, 0, 0, SRCCOPY ); 
 
    if( FAILED( hr = lpDDSurface->ReleaseDC( hDC ) ) ) 
        return NULL; 
 
    DeleteDC( hDCImage );					//此处并没有DeleteObject( hBmp ) 
 
    return lpDDSurface; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
HRESULT CreateSurfaceOfBmp( LPDIRECTDRAW7 lpdd,  
							LPDIRECTDRAWSURFACE7 *ppSurface, 
							char *szFileName,  
							bool isSysMemory,  
							bool isColorKey, DWORD ColorKey ) 
{	 
	if ( ppSurface == NULL ) 
		return E_FAIL; 
 
	LPDIRECTDRAWSURFACE7 lpDDSurface = NULL; 
	HBITMAP hBmp; 
	 
 
	hBmp = (HBITMAP)LoadImage( NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE ); 
 
 
	if ( hBmp == NULL ) 
		return E_FAIL; 
	BITMAP bmp; 
	GetObject( hBmp, sizeof(bmp), &bmp ); 
	 
	HRESULT hr = CreateSurfaceHelp( lpdd, &lpDDSurface, bmp.bmWidth, bmp.bmHeight, isSysMemory, isColorKey, ColorKey ); 
 
	if ( lpDDSurface == NULL ) 
		return hr; 
 
	if ( LoadBmpToSurfaceFromHBmp( hBmp, lpDDSurface, 0, 0 ) == NULL ) 
	{ 
		SafeRelease( lpDDSurface ); 
		return E_FAIL; 
	} 
 
	*ppSurface = lpDDSurface; 
	return hr; 
} 
 
 
//------------------------------------------------  
inline WORD Alpha_Pixel565(WORD sour, WORD dest ) 
{ 
	WORD rgbTemp; 
 
	rgbTemp = ( ( sour >> 1 ) & 0x7bef ) + ( ( dest >> 1 )  & 0x7bef ) ; 
 
	return rgbTemp; 
} 
 
//------------------------------------------------  
inline WORD Alpha_Pixel555(WORD sour, WORD dest ) 
{ 
	WORD rgbTemp; 
 
	rgbTemp = ( ( sour >> 1 ) & 0x3def ) + ( ( dest >> 1 )  & 0x3def ) ; 
 
	return rgbTemp; 
} 
 
inline WORD Alpha_WindSoul_565( DWORD src, DWORD dest, DWORD alpha ) 
{ 
	src = ( src | ( src << 16 ) ) & 0x7e0f81f; 
	dest= ( dest| ( dest<< 16 ) ) & 0x7e0f81f; 
	DWORD result = ( ( ( src - dest ) * alpha / 32 ) + dest ) & 0x7e0f81f; 
	return (WORD)(( result & 0xffff ) | ( result >> 16 )); 
} 
 
inline WORD Alpha_WindSoul_555( DWORD src, DWORD dest, DWORD alpha ) 
{ 
	src = ( src | ( src << 16 ) ) & 0x3E07C1F; 
	dest= ( dest| ( dest<< 16 ) ) & 0x3E07C1F; 
	DWORD result = ( ( ( src - dest ) * alpha / 32 ) + dest ) & 0x3E07C1F; 
	return (WORD)(( result & 0xffff ) | ( result >> 16 )); 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void AlphaSurfaceRect16( LPDIRECTDRAWSURFACE7 lpSourceSur, LPDIRECTDRAWSURFACE7 lpDestSur,   
						RECT *rcSrc, RECT *rcDest, bool is565, bool isColorKey, WORD ColorKey, DWORD alpha ) 
{ 
	DDSURFACEDESC2 ddsd; 
	WORD *lpSourceBuf;  //指向源页面的指针 
	WORD *lpDestBuf;	//目标页面指针 
	int iPitch; 
	int iPitch2; 
	DWORD iW			= 0; 
	DWORD iH			= 0; 
	DWORD i, j; 
 
	ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了 
	if ( lpSourceSur->Lock( rcSrc, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ) 
		!= DD_OK ) 
	{ 
		lpDestSur->Unlock( NULL ); 
		return; 
	} 
	lpSourceBuf = (WORD *)ddsd.lpSurface;  //注意这里有个类型转换 
	iPitch = ddsd.lPitch >> 1; 
	iW = ddsd.dwWidth; 
	iH = ddsd.dwHeight; 
 
	ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了 
	if ( lpDestSur->Lock( rcDest, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) 
		!= DD_OK ) 
	{ 
		return; 
	} 
	lpDestBuf = (WORD *)ddsd.lpSurface;  //注意这里有个类型转换 
	iPitch2 = ddsd.lPitch >> 1; 
 
	if ( ddsd.dwWidth < iW ) 
		iW = ddsd.dwWidth; 
 
	if ( ddsd.dwHeight < iH ) 
		iH = ddsd.dwHeight; 
	 
	if ( isColorKey ) 
	{ 
		WORD data; 
		if ( is565 ) 
		{ 
			for ( i = 0; i < iH; i++ ) 
			{ 
				for ( j = 0; j < iW; j++ ) 
				{ 
					data = lpDestBuf[ i * iPitch2 + j ]; 
 
					if ( data != ColorKey ) 
						lpDestBuf[ i * iPitch2 + j ]  
						= Alpha_WindSoul_565( lpSourceBuf[ i * iPitch + j ], data, alpha );//Alpha_Pixel565( data, lpDestBuf[ i * iPitch2 + j ] ); 
				} 
			} 
		} 
		else 
		{ 
			for ( i = 0; i < iH; i++ ) 
			{ 
				for ( j = 0; j < iW; j++ ) 
				{ 
					data = lpDestBuf[ i * iPitch2 + j ]; 
 
					if ( data != ColorKey ) 
						lpDestBuf[ i * iPitch2 + j ]  
						= Alpha_WindSoul_555( lpSourceBuf[ i * iPitch + j ], data, alpha ); 
				} 
			} 
		} 
	} 
	else 
	{ 
		if ( is565 ) 
		{ 
			for ( i = 0; i < iH; i++ ) 
			{ 
				for ( j = 0; j < iW; j++ ) 
				{ 
					WORD data = lpDestBuf[ i * iPitch2 + j ]; 
					lpDestBuf[ i * iPitch2 + j ] = Alpha_WindSoul_565( lpSourceBuf[ i * iPitch + j ], data, alpha ); 
				} 
			} 
		} 
		else 
		{ 
			for ( i = 0; i < iH; i++ ) 
			{ 
				for ( j = 0; j < iW; j++ ) 
				{ 
					WORD data = lpDestBuf[ i * iPitch2 + j ]; 
					lpDestBuf[ i * iPitch2 + j ] = Alpha_WindSoul_555( lpSourceBuf[ i * iPitch + j ], data, alpha ); 
				} 
			} 
		} 
	} 
 
	lpSourceSur->Unlock( NULL ); 
	lpDestSur->Unlock( NULL ); 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void AlphaHalf16(	LPDIRECTDRAWSURFACE7 lpSourceSur, LPDIRECTDRAWSURFACE7 lpDestSur,  
					RECT *rcSrc, RECT *rcDest, bool is565, bool isColorKey, WORD ColorKey ) 
{ 
	DDSURFACEDESC2 ddsd; 
	WORD *lpSourceBuf;  //指向源页面的指针 
	WORD *lpDestBuf;	//目标页面指针 
	int iPitch; 
	int iPitch2; 
	int iW			= 0; 
	int iH			= 0; 
	int i, j; 
 
	ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了 
	if ( lpSourceSur->Lock( rcSrc, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ) 
		!= DD_OK ) 
	{ 
		lpDestSur->Unlock( NULL ); 
		return; 
	} 
	lpSourceBuf = (WORD *)ddsd.lpSurface;  //注意这里有个类型转换 
	iPitch = ddsd.lPitch >> 1; 
	iW = ddsd.dwWidth; 
	iH = ddsd.dwHeight; 
 
	ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了 
	if ( lpDestSur->Lock( rcDest, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) 
		!= DD_OK ) 
	{ 
		return; 
	} 
	lpDestBuf = (WORD *)ddsd.lpSurface;  //注意这里有个类型转换 
	iPitch2 = ddsd.lPitch >> 1; 
 
	if ( ddsd.dwWidth < iW ) 
		iW = ddsd.dwWidth; 
 
	if ( ddsd.dwHeight < iH ) 
		iH = ddsd.dwHeight; 
	 
	if ( isColorKey ) 
	{ 
		WORD data; 
		if ( is565 ) 
		{ 
			for ( i = 0; i < iH; i++ ) 
			{ 
				for ( j = 0; j < iW; j++ ) 
				{ 
					data = lpDestBuf[ i * iPitch2 + j ]; 
 
					if ( data != ColorKey ) 
						lpDestBuf[ i * iPitch2 + j ] = Alpha_Pixel565( lpSourceBuf[ i * iPitch + j ], data ); 
				} 
			} 
		} 
		else 
		{ 
			for ( i = 0; i < iH; i++ ) 
			{ 
				for ( j = 0; j < iW; j++ ) 
				{ 
					data = lpDestBuf[ i * iPitch2 + j ]; 
 
					if ( data != ColorKey ) 
						lpDestBuf[ i * iPitch2 + j ] = Alpha_Pixel555( lpSourceBuf[ i * iPitch + j ], data ); 
				} 
			} 
		} 
	} 
	else 
	{ 
		if ( is565 ) 
		{ 
			for ( i = 0; i < iH; i++ ) 
			{ 
				for ( j = 0; j < iW; j++ ) 
				{ 
					WORD data = lpDestBuf[ i * iPitch2 + j ]; 
					lpDestBuf[ i * iPitch2 + j ] = Alpha_Pixel565( lpSourceBuf[ i * iPitch + j ], data ); 
				} 
			} 
		} 
		else 
		{ 
			for ( i = 0; i < iH; i++ ) 
			{ 
				for ( j = 0; j < iW; j++ ) 
				{ 
					WORD data = lpDestBuf[ i * iPitch2 + j ]; 
					lpDestBuf[ i * iPitch2 + j ] = Alpha_Pixel555( lpSourceBuf[ i * iPitch + j ], data ); 
				} 
			} 
		} 
	} 
 
	lpSourceSur->Unlock( NULL ); 
	lpDestSur->Unlock( NULL ); 
} 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void DrawTextOnSurface( LPDIRECTDRAWSURFACE7 lpSurface, const char *szText, int TextLen, int x, int y, DWORD Color ) 
{ 
	HDC  hDC; 
	if ( lpSurface->GetDC( &hDC ) == DD_OK ) 
	{ 
		//SetBkColor( hDCBack, NULL ); 
		SetBkMode( hDC, TRANSPARENT );		//背景透明 
		SetTextColor( hDC, Color ); 
		HFONT hFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT); 
		SelectObject(hDC, hFont); 
		TextOut( hDC, x, y, szText, TextLen ); 
 
		lpSurface->ReleaseDC( hDC ); 
	} 
} 
 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
LPDIRECTDRAWSURFACE7 LoadBmpFromMemory( BYTE *pData, LPDIRECTDRAW7 lpdd,  
									   LPDIRECTDRAWSURFACE7 lpDDSurface, RECT *pDestRect, 
									   bool isSysMemory ) 
{ 
	debug_assert( pData != NULL ); 
 
	BITMAPFILEHEADER	bmfh;	//位图的文件头 
	BITMAPINFOHEADER	bmih;	//位图信息头 
 
	bmfh = READ_MEMORY( pData, BITMAPFILEHEADER); 
	pData += sizeof(bmfh); 
	//int offset = sizeof(bmfh); 
	//memcpy( &bmfh, pData, sizeof(bmfh) ); 
 
	//ReadMemory( (BYTE *)&bmih, pData, sizeof(bmih), offset ); 
	//offset += sizeof(bmih); 
 
	bmih = READ_MEMORY( pData, BITMAPINFOHEADER ); 
	pData += sizeof(bmih); 
 
	//计算补码 
	int byte = bmih.biBitCount / 8; 
	int iResidue = (bmih.biWidth * byte) % 4; 
	 
	if ( iResidue != 0 ) iResidue = 4 - iResidue; 
 
	if ( lpDDSurface == NULL ) 
	{ 
		CreateSurfaceHelp( lpdd, &lpDDSurface, bmih.biWidth, bmih.biHeight, isSysMemory, false, 0 ); 
	} 
 
	//锁定页面: 
	DDSURFACEDESC2 ddsd; 
	ddsd.dwSize = sizeof(ddsd); 
 
	WORD *buf16; 
	int iW, iH, iPitch; 
 
	if ( lpDDSurface->Lock( pDestRect, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) != DD_OK ) 
		return NULL;  
	buf16 = (WORD *)ddsd.lpSurface; 
	iPitch = ddsd.lPitch >> 1; 
	iW = ddsd.dwWidth; 
	iH = ddsd.dwHeight; 
 
	if ( iW < bmih.biWidth || iH < bmih.biHeight ) 
	{ 
		lpDDSurface->Unlock( 0 ); 
		return NULL; 
	} 
 
	//开始拷贝数据 
	bool is565 = GetEasyDrawPointer()->Is565(); 
	//pData += bmfh.bfOffBits; 
	//Show( bmfh.bfOffBits ); 
	if ( bmih.biBitCount == 32 )			//32位图 
	{ 
		int data; 
		int r, g, b; 
		if ( is565 )						//565 
		{ 
			for ( int i = bmih.biHeight-1; i >= 0; --i ) 
			{ 
				for ( int j = 0; j < bmih.biWidth; ++j ) 
				{ 
					//ReadMemory( (BYTE *)&data, pData, 4, offset ); 
					data = READ_MEMORY( pData, int ); 
					pData += 4; 
 
					r = GET_R_32( data ); 
					g = GET_G_32( data ); 
					b = GET_B_32( data ); 
					buf16[ i * iPitch + j ] = RGBTO565( r, g, b ); 
				} 
			} 
		} 
		else 
		{ 
			for ( int i = bmih.biHeight-1; i >= 0; --i ) 
			{ 
				for ( int j = 0; j < bmih.biWidth; ++j ) 
				{ 
					data = READ_MEMORY( pData, int ); 
					pData += 4; 
 
					r = GET_R_32( data ); 
					g = GET_G_32( data ); 
					b = GET_B_32( data ); 
					buf16[ i * iPitch + j ] = RGBTO555( r, g, b ); 
				} 
			} 
		} 
	} 
	else if ( bmih.biBitCount == 24 )		//24位图 
	{ 
		BYTE r, g, b; 
		if ( is565 ) 
		{ 
			for ( int i = bmih.biHeight - 1; i >= 0 ; --i ) 
			{ 
				for ( int j = 0; j < bmih.biWidth; ++j ) 
				{ 
					b = READ_MEMORY( pData, BYTE );			++pData; 
					g = READ_MEMORY( pData, BYTE );			++pData; 
					r = READ_MEMORY( pData, BYTE );			++pData; 
 
					buf16[ i * iPitch + j ] = RGBTO565( r, g, b ); 
				} 
				pData += iResidue; 
			} 
		} 
		else 
		{ 
			for ( int i = bmih.biHeight-1; i >= 0; --i ) 
			{ 
				for ( int j = 0; j < bmih.biWidth; ++j ) 
				{ 
					b = READ_MEMORY( pData, BYTE );			++pData; 
					g = READ_MEMORY( pData, BYTE );			++pData; 
					r = READ_MEMORY( pData, BYTE );			++pData; 
 
					buf16[ i * iPitch + j ] = RGBTO555( r, g, b ); 
				} 
				pData += iResidue; 
			} 
		} 
	} 
	else if ( bmih.biBitCount == 16 ) 
	{ 
		bool isBmp565 = true;						//判断位图是565还是555格式 
		if ( bmih.biCompression == BI_RGB ) 
			isBmp565 = false; 
		else  
		{ 
			int mask; 
			memcpy( &mask, pData, 4 ); 
			pData += 12; 
			if ( mask == 0x7c00 ) 
				isBmp565 = false; 
		} 
		 
		WORD data; 
		if ( isBmp565 == is565 ) 
		{ 
			for ( int i = iH - 1; i >= 0; --i ) 
			{ 
				for ( int j = 0; j < iW; ++j ) 
				{ 
					data = READ_MEMORY( pData, WORD ); 
					buf16[ i * iPitch + j ] = data; 
					pData += 2; 
				} 
				pData += iResidue; 
			} 
		} 
		else if ( is565 && !isBmp565 ) 
		{ 
			for ( int i = iH - 1; i >= 0; --i ) 
			{ 
				for ( int j = 0; j < iW; ++j ) 
				{ 
					data = READ_MEMORY( pData, WORD ); 
					pData += 2; 
					buf16[ i * iPitch + j ] = CHANGE_555_TO_565( data ); 
				} 
				pData += iResidue; 
			} 
		} 
		else if ( !is565 && isBmp565 ) 
		{ 
			for ( int i = iH - 1; i >= 0; --i ) 
			{ 
				for ( int j = 0; j < iW; ++j ) 
				{ 
					data = READ_MEMORY( pData, WORD ); 
					buf16[ i * iPitch + j ] = CHANGE_565_TO_555( data ); 
					pData += 2; 
				} 
				pData += iResidue; 
			} 
		} 
		 
	} 
	else  
	{ 
		return NULL; 
	} 
 
	lpDDSurface->Unlock( 0 ); 
	return lpDDSurface; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
WORD RGB_To_565( int r, int g, int b ) 
{ 
	return WORD( ((r%32) << 11) + ((g%64) << 5 ) + (b%32) ); 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
WORD RGB_To_555( int r, int g, int b ) 
{ 
	return WORD( ((r%32) << 10) + ((g%32) << 5 ) + (b%32) ); 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CopySurfaceToBmp16( LPDIRECTDRAWSURFACE7 lpDDSurface, char *szFileName, RECT *pRect, bool is565 ) 
{ 
	debug_assert( lpDDSurface != NULL && szFileName != NULL ); 
 
	DDSURFACEDESC2 ddsd; 
	WORD *lpBuffer;				//指向页面的指针 
	int iPitch;	 
	int iResidue	= 0;		//补上的可以被4整除的数,单位字节 
	int iW			= 0; 
	int iH			= 0; 
 
	 
	BITMAPFILEHEADER	bmfh;	//位图的文件头 
	BITMAPINFOHEADER	bmih;	//位图信息头 
	DWORD dwRMask	= 0xf800;	//565的遮码 
	DWORD dwGMask	= 0x07e0; 
	DWORD dwBMask	= 0x001f; 
 
	if ( !is565 )				//如果显示模式不是565的话 
	{ 
		dwRMask = 0x7c00; 
		dwGMask = 0x03e0; 
	} 
 
	FILE *fp = fopen( szFileName, "wb+" ); 
	if ( fp == NULL ) 
		return false; 
 
	//锁定主页面: 
	ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了 
	if ( lpDDSurface->Lock( pRect, &ddsd,  
		DDLOCK_SURFACEMEMORYPTR | DDLOCK_READONLY | DDLOCK_WAIT, NULL ) != DD_OK ) 
	{ 
		fclose(fp); 
		return false; 
	} 
	 
	lpBuffer = (WORD *)ddsd.lpSurface;  //注意这里有个类型转换 
	iPitch = ddsd.lPitch >> 1; 
 
	if ( pRect == NULL ) 
	{ 
		iW = ddsd.dwWidth; 
		iH = ddsd.dwHeight; 
	} 
	else 
	{ 
		iW = pRect->right - pRect->left; 
		iH = pRect->bottom- pRect->top; 
	} 
	iResidue = (iW % 2) * 2;			//计算出补数  
 
	//写入文件头: 
	bmfh.bfType = 'MB';					//注意这里是MB,而不是BM 
	bmfh.bfSize = 0x36 + 12 + ( iW + iResidue / 2 ) * iH * 2; 
	bmfh.bfOffBits = 0x36 + 12; 
	bmfh.bfReserved1 = 0; 
	bmfh.bfReserved2 = 0; 
 
	fwrite( &bmfh, sizeof(bmfh), 1, fp ); 
 
	//写入信息头: 
	bmih.biSize = sizeof(BITMAPINFOHEADER);  
	bmih.biWidth = iW; 
	bmih.biHeight = iH; 
	bmih.biPlanes = 1; 
	bmih.biBitCount = 16;	 
	bmih.biCompression = BI_BITFIELDS;	//16位的565格式,若为其它格式,图像失真 
	bmih.biSizeImage = ( iW + iResidue / 2 ) * iH * 2; 
	bmih.biXPelsPerMeter = 0; 
	bmih.biYPelsPerMeter = 0; 
	bmih.biClrUsed = 0; 
	bmih.biClrImportant = 0; 
 
	fwrite( &bmih, sizeof(bmih), 1, fp ); 
	fwrite( &dwRMask, 4, 1, fp ); 
	fwrite( &dwGMask, 4, 1, fp ); 
	fwrite( &dwBMask, 4, 1, fp );				//写入遮码			 
 
 
	//开始写入数据: 
	fseek( fp, 0x36+12, SEEK_SET ); 
 
	for ( int i = iH - 1; i >= 0; i-- )					//i为高 
	{ 
		for ( int j = 0; j < iW; j++ )			//j为宽 
		{ 
			WORD word = lpBuffer[ i * iPitch + j ]; 
			fwrite( &word, 2, 1, fp ); 
		}	 
		fseek( fp, iResidue, SEEK_CUR );		//跳过补数部份 
	} 
 
	lpDDSurface->Unlock( NULL ); 
	fclose(fp); 
	return true; 
} 
/* 
//-------------------------------------------------------载入JPEG图片----------------------------------------------- 
#define RGB555(r, g, b) ((r >> 3) | ((g >> 3) << 5) | ((b >> 3) << 10)) 
#define RGB565(r, g, b) ((r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11)) 
 
//16Bit Color Formats 
#define PF_555  1 
#define PF_565  2 
 
//Color modes 
const int C16BIT = 16; 
const int C24BIT = 24; 
#define C32BIT  32 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
HRESULT LoadJpegHelp(  	LPDIRECTDRAW7 lpdd,  
						LPDIRECTDRAWSURFACE7 *ppSurface,	\ 
						char *szFileName,  
						LPDIRECTDRAWSURFACE7 surf,	\ 
						bool isSysMemory,			\ 
						bool isColorKey,			\ 
						DWORD ColorKey,				\ 
						bool is565 ) 
{ 
	if ( ppSurface == NULL ) 
		return E_FAIL; 
 
	//Error handle 
	IJLERR jerr; 
	int  nPixelFormat = PF_555; 
	//Create the JPEG object 
	JPEG_CORE_PROPERTIES jcprops; 
	 
	 
	//Get green bitmask and set pixel format     
	if( is565 ) 
		nPixelFormat = PF_565; 
	else  
		nPixelFormat = PF_555; 
	 
	 
	//Initialize the JPEG object 
	jerr = ijlInit(&jcprops); 
	if (jerr != IJL_OK) 
		return E_FAIL; 
	 
 
	//Set the IJL data source as a filename 
	jcprops.JPGFile = szFileName; 
		 
	//Read JPEG parameters from the file 
	jerr = ijlRead(&jcprops, IJL_JFILE_READPARAMS); 
 
	 
	//Make sure Parameter read was successful 
	if (jerr != IJL_OK) 
		return E_FAIL; 
 
	 
	//Set up the DIB specification for the JPEG decoder 
	jcprops.DIBWidth    = jcprops.JPGWidth; 
	jcprops.DIBHeight   = jcprops.JPGHeight; //Implies a bottom-up DIB. 
	jcprops.DIBChannels = 3; 
	jcprops.DIBColor    = IJL_BGR; 
	jcprops.DIBPadBytes = 0; //IJL_DIB_PAD_BYTES(jcprops.JPGWidth,3); 
 
	 
	//jcprops.DIBHeight = -jcprops.JPGHeight; 
	//Set the JPG color space ... this will always be somewhat of an 
	//educated guess at best because JPEG is "color blind" (i.e., 
	//nothing in the bit stream tells you what color space the data was 
	//encoded from. However, in this example we assume that we are 
	//reading JFIF files which means that 3 channel images are in the 
	//YCbCr color space and 1 channel images are in the Y color space. 
	switch(jcprops.JPGChannels) 
	{ 
	case 1: jcprops.JPGColor = IJL_G; 
		break; 
		 
	case 3: jcprops.JPGColor = IJL_YCBCR; 
		break; 
		 
	default: 
		//This catches everything else, but no color twist will be 
		//performed by the IJL. 
		jcprops.DIBColor = (IJL_COLOR)IJL_OTHER; 
		jcprops.JPGColor = (IJL_COLOR)IJL_OTHER; 
		break; 
	} 
 
	//Prepare a 24Bit buffer to receive image data 
	BYTE *buffer24; 
	 
	//Determine the required size 
	long szbuff24 = jcprops.DIBWidth * 3 * jcprops.DIBHeight; 
 
	//Resize the buffer 
	buffer24 = new BYTE [szbuff24]; 
	if (buffer24 == NULL) 
		return E_FAIL; 
 
 
	//Read JPEG image data into our 24bit buffer 
	jcprops.DIBBytes    = reinterpret_cast(buffer24); 
	jerr = ijlRead(&jcprops, IJL_JFILE_READWHOLEIMAGE); 
	 
	//Make sure the read was successful 
	if (jerr != IJL_OK) 
		return E_FAIL; 
	 
	HBITMAP hbm = NULL; 
 
	//Convert to current CLRMODE 
 
	//Create a 16bit buffer 
	WORD *buffer16; 
	long szbuff16; 
	 
	//determine the size of our buffer 
	szbuff16 = jcprops.DIBWidth * 2 * jcprops.DIBHeight; 
 
	//resize the buffer and make sure resize works 
	buffer16 = new WORD [szbuff16]; 
	if (buffer16 == NULL) 
		return E_FAIL; 
	 
	//Start at the beginning of the buffer 
	 
	 
	//Step through the 24bit buffer 
	//Retrieve 3 channels at a time and convert their values to 16bit 
	//Check the pixel format and write the color data 
	//to the 16bit buffer. After the write, advance the 
	//16bit buffer by one. 
	 
	long j = 0; 
	if ( nPixelFormat == PF_555 ) 
	{ 
		for (long i = 0; i < szbuff24; i += 3)    
		{ 
			buffer16[j++] = RGB555(buffer24[i], buffer24[i + 1], 
				buffer24[i + 2]); 
		} 
	} 
	else 
	{ 
		for (long i = 0; i < szbuff24; i += 3)    
		{ 
				buffer16[j++] = RGB565(buffer24[i], buffer24[i + 1], 
				buffer24[i + 2]); 
		} 
	} 
 
	 
	//Create the bitmap using the new 16bit buffer    
	hbm = CreateBitmap (jcprops.JPGWidth, jcprops.JPGHeight, 1, 
		C16BIT, buffer16); 
	if(hbm == NULL) 
		return NULL; 
	 
	//remove the new buffer 
	delete [] buffer16; 
	 
	//remove the old buffer 
	delete [] buffer24; 
	ijlFree(&jcprops); 
 
 
	//If DirectDraw Surface is NULL, create it 
	HRESULT hr; 
	if ( *ppSurface == NULL ) 
	{ 
		hr = CreateSurfaceHelp( lpdd, ppSurface, jcprops.JPGWidth, jcprops.JPGHeight, isSysMemory, isColorKey, ColorKey ); 
		if ( *ppSurface == NULL ) 
			return hr; 
	} 
	 
	//Copy bitmap data to DirectDraw Surface 
	if ( LoadBmpToSurfaceFromHBmp( hbm, *ppSurface, 0, 0 ) == NULL ) 
	{ 
		SafeRelease( *ppSurface ); 
		return E_FAIL; 
	} 
	 
	// clean up and destroy the JPEG Decompressor 
	 
	DeleteObject(hbm); 
	return hr; 
}*/