📄 easydraw.cpp
字号:
#include "stdafx.h"
#include "EasyDraw.h"
#include <windowsx.h>
#include <stdio.h>
EasyDraw theEasyDraw;
EasyDraw::EasyDraw()
{
lpDD = NULL;
lpDDSBack = NULL;
lpDDSPrimary = NULL;
lpDDSTemp = NULL;
GameHwnd = NULL; //一个离屏页面,用于完成各种特效
}
EasyDraw::~EasyDraw()
{
if ( lpDD != NULL )
{
SafeRelease(lpDDSTemp);
SafeRelease(lpDDSBack);
SafeRelease(lpDDSPrimary);
lpDD->SetCooperativeLevel( GameHwnd, DDSCL_NORMAL );
SafeRelease(lpDD);
GameHwnd = NULL;
}
}
//565转555
DWORD EasyDraw::ChangeColorKey( DWORD colorkey )
{
DWORD w = colorkey;
// return CHANGE_565_TO_555( w );
return w;
}
bool EasyDraw::InitDDraw(HWND hwnd, bool isWindowed, int iW, int iH)
{
m_iWidth=iW;
m_iHeight=iH;
DDSURFACEDESC2 ddsd; // DirectDraw的页面描述
HRESULT hr;
//创建lpdd7对象:
hr = DirectDrawCreateEx(NULL, (void **)&lpDD, IID_IDirectDraw7, NULL);
if ( hr != DD_OK )
{
return false;
}
SetWindowLong( hwnd, GWL_STYLE, WS_POPUP );
hr = lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
if ( hr != DD_OK )
{
return false;
}
//设置屏幕模式:
hr = lpDD->SetDisplayMode( iW, iH, 16, 0, 0 ); //只支持16位模式
if ( hr != DD_OK )
{
return false;
}
//创建主页面:
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 = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
if ( hr != DD_OK )
{
return false;
}
//创建后台页面:
DDSCAPS2 ddscaps;
ZeroMemory( &ddscaps, sizeof( ddscaps ) );
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
hr = lpDDSPrimary->GetAttachedSurface( &ddscaps, &lpDDSBack );
if ( hr != DD_OK )
{
return false;
}
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; //这是离屏页面
ddsd.dwHeight=300; //高
ddsd.dwWidth=300; //宽
if ( DD_OK != lpDD->CreateSurface( &ddsd, &lpDDSTemp, NULL ) )
return FALSE; //创建放背景图的页面
//如还有别的页面可在此处继续创建
return TRUE;
}
void EasyDraw::Filp()
{
// RECT rect={0,0,1024,768};
RECT rect={0,0,800,600};
lpDDSPrimary->BltFast( 0, 0,this->lpDDSBack,&rect, DDBLTFAST_NOCOLORKEY );
}
//-------------------------------------------------EasyDraw辅助函数------------------------------------------------------
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
EasyDraw * InitEasyDraw( HWND hwnd, bool isWindowed, int iW, int iH )
{
if ( theEasyDraw.InitDDraw( hwnd, isWindowed, iW, iH ) == false )
{
return NULL;
}
return &theEasyDraw;
}
EasyDraw *GetEasyDrawPointer()
{
return &theEasyDraw;
}
//////////////////////////////////////////////////////////////////////
//是否有关键色
//////////////////////////////////////////////////////////////////////
void SetColorKeyHelp( LPDIRECTDRAWSURFACE7 lpDDSurface, DWORD ColorKey)
{
DDCOLORKEY ddck;
ddck.dwColorSpaceLowValue = ColorKey;
ddck.dwColorSpaceHighValue = ColorKey;
lpDDSurface->SetColorKey( DDCKEY_SRCBLT, &ddck );
}
//////////////////////////////////////////////////////////////////////
//创建一个离屏页面
//参数:页面宽高,是否使用系统内存,是否有关键色
//////////////////////////////////////////////////////////////////////
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;
}
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 )
{
lpDDSurface->Release();
lpDDSurface=NULL;
return E_FAIL;
}
*ppSurface = lpDDSurface;
return hr;
}
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;
}
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -