📄 core_graphics.cpp
字号:
fputc( p[1], fp); // g
fputc( p[2], fp); // r
if( j==m_iWidth-1 && i==0 )
break;
p += 4;
}
if( i==0 )
p -= (ddsd.lPitch<<1)-(iPitch<<2) - 4;
else
p -= (ddsd.lPitch<<1)-(iPitch<<2);
}
}
else if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
{
int iPitch = ((2-ddsd.dwWidth&1)&1);
p += (m_iHeight - 1) * ddsd.lPitch;
for(int i=0; i<m_iHeight; i++)
{
for(int j=0; j<m_iWidth; j++)
{
fputc( g_pDirectDraw->GetB(p[0]), fp); // b
fputc( g_pDirectDraw->GetG(p[0],p[1]), fp); // g
fputc( g_pDirectDraw->GetR(p[1]), fp); // r
if( j==m_iWidth-1 && i==0 )
break;
p += 2;
}
if( i==0 )
p -= (ddsd.lPitch<<1)-(iPitch<<1) - 2;
else
p -= (ddsd.lPitch<<1)-(iPitch<<1); // 指针转到上一行的开始
}
}
fclose(fp);
}
m_lpDDS->Unlock( NULL );
return TRUE;
}
void cGraphics::Release()
{
//SAFE_RELEASE( m_lpDDS );
if( m_lpDDS )
{
m_lpDDS->Release();
m_lpDDS = NULL;
}
}
void cGraphics::Lock(void** pSurface, int* lPitch )
{
DDSURFACEDESC2 ddsd;
memset( &ddsd, 0, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
m_lpDDS->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
*pSurface = ddsd.lpSurface;
*lPitch = ddsd.lPitch;
}
void cGraphics::Unlock()
{
m_lpDDS->Unlock( NULL );
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
cDirectDraw::cDirectDraw()
{
g_pDirectDraw = this;
m_lpDD = NULL;
m_hWnd = NULL;
m_iHeight = 600;
m_iWidth = 800;
m_lpDDS_Prim = NULL;
m_lpDDS_Back = NULL;
}
cDirectDraw::~cDirectDraw()
{
Release();
}
BOOL cDirectDraw::Create( HWND hWnd, HINSTANCE hInst, BOOL bFullScreen, int iWidth, int iHeight )
{
m_lpDD = NULL;
m_hWnd = hWnd;
m_iWidth = iWidth;
m_iHeight = iHeight;
m_bExclusive = bFullScreen;
HRESULT hr;
//Create DirectDraw
hr = DirectDrawCreateEx( NULL, (void**)&m_lpDD, IID_IDirectDraw7, NULL );
if( hr == DDERR_INVALIDDIRECTDRAWGUID )
{
MessageBox( GetActiveWindow(), _T("需要DirectX7.0版本,请升级你DirectX到7.0版!"), _T("ERROR Info"), MB_OK );
exit(0);
return FALSE;
}
if( hr != DD_OK )
return FALSE;
//Set Cooperative Level
if( m_bExclusive )
hr = m_lpDD->SetCooperativeLevel( m_hWnd, DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE);
else
hr = m_lpDD->SetCooperativeLevel( NULL, DDSCL_NORMAL );//m_hWnd is better than NULL
//Set Display Mode
if( m_bExclusive )
SetDisplayMode( m_iWidth, m_iHeight );
//Create Prim Surface
DDSURFACEDESC2 ddsd;
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS;
//看网上的一篇文章,说这需要改成ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
//原因:2D情况下,表面的渲染是由CPU而不是显卡来完成的!当然没有直接操纵系统内存快。
//ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_SYSTEMMEMORY; //faster in Exclusive Mode
if( m_bExclusive )
{
ddsd.ddsCaps.dwCaps |= DDSCAPS_FLIP|DDSCAPS_COMPLEX;
ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount=1;
}
hr = m_lpDD->CreateSurface( &ddsd, (LPDIRECTDRAWSURFACE7*)(&m_lpDDS_Prim), NULL );
if( hr != DD_OK )
return FALSE;
if( !m_bExclusive )
{
LPDIRECTDRAWCLIPPER pcClipper;
hr = m_lpDD->CreateClipper( 0, &pcClipper, NULL );
if(hr != DD_OK)
return FALSE;
hr = pcClipper->SetHWnd( 0, m_hWnd );
if(hr != DD_OK)
return FALSE;
//hr = m_lpDDS->SetClipper(pcClipper);
hr = m_lpDDS_Prim->SetClipper( pcClipper );
if(hr != DD_OK)
return FALSE;
pcClipper->Release();
}
//Create Back Surface
if( m_bExclusive )
{
DDSCAPS2 dds;
memset(&dds,0,sizeof(dds));
dds.dwCaps = DDSCAPS_BACKBUFFER;
hr = m_lpDDS_Prim->GetAttachedSurface( &dds, (LPDIRECTDRAWSURFACE7*)(&m_lpDDS_Back) );
if( hr != DD_OK)
return FALSE;
}
else
{
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
ddsd.dwHeight = m_iHeight;
ddsd.dwWidth = m_iWidth;
hr = m_lpDD->CreateSurface( &ddsd, (LPDIRECTDRAWSURFACE7*)&m_lpDDS_Back, NULL );
if( hr != DD_OK )
return FALSE;
}
//Create Input Device
//如果执行到这,而此时程序窗口不是active状态时,创建失败
m_bInputSucc = TRUE;
if( !m_input.Init( m_hWnd, hInst ) )//m_hWnd -> GetActiveWindow()
{
//DebugMB( _T( "Input Device Init Failed !" ) );
m_bInputSucc = FALSE;
}
if( !m_keyboardDev.Create( &m_input, KEYBOARD, TRUE ) )
{
//DebugMB( _T( "Keyboard Device Init Failed !" ) );
m_bInputSucc = FALSE;
}
if( !m_mouseDev.Create( &m_input, MOUSE, TRUE ) )
{
//DebugMB( _T( "Mouse Device Init Failed !" ) );
m_bInputSucc = FALSE;
}
//Create Music here:
//......
//m_sound.Init( GethWnd() );
//m_musicChannel.Create( &m_sound );
return TRUE;
}
BOOL cDirectDraw::LoadToBackSurface( cGraphics* offScreenGraphics, int left, int top, LPRECT srcRect/* =NULL */)
{
if( offScreenGraphics == NULL || offScreenGraphics->GetSurface() == NULL )
return FALSE;
LPRECT pRect = srcRect;
if( pRect == NULL )
{
pRect = new RECT;
DDSURFACEDESC2 ddsd;
memset( &ddsd, 0, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
offScreenGraphics->GetSurface()->GetSurfaceDesc( &ddsd );
pRect->left = 0;
pRect->top = 0;
pRect->right = ddsd.dwWidth;
pRect->bottom = ddsd.dwHeight;
}
//在此进行矩形的合理性判断
if( left >= m_iWidth || top >= m_iHeight )
return FALSE;
if( left < 0 )
{
pRect->left -= left;
left = 0;
}
if( top < 0 )
{
pRect->top -= top;
top = 0;
}
if( left + pRect->right-pRect->left - m_iWidth >= 0 )
pRect->right = m_iWidth - left;
if( top + pRect->bottom - pRect->top - m_iHeight >= 0 )
pRect->bottom = m_iHeight-top;
if( pRect->right - pRect->left <= 0 )
return FALSE;
if( pRect->bottom - pRect->top <= 0 )
return FALSE;
//在这里进行改进,判断是否ColorKey.
HRESULT hr;
if( offScreenGraphics->m_bColorKey )
{
hr = m_lpDDS_Back->BltFast( left, top, offScreenGraphics->GetSurface(), pRect, DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY );
}
else
{
hr = m_lpDDS_Back->BltFast( left, top, offScreenGraphics->GetSurface(), pRect, DDBLTFAST_WAIT );
}
switch( hr )
{
case DDERR_SURFACELOST:
return FALSE;
break;
case DDERR_SURFACEBUSY:
return FALSE;
break;
case DDERR_INVALIDOBJECT:
return FALSE;
break;
case DDERR_INVALIDRECT:
return FALSE;
break;
case DDERR_EXCEPTION:
return FALSE;
break;
case DDERR_UNSUPPORTED:
return FALSE;
break;
case DDERR_GENERIC:
return FALSE;
break;
case DDERR_NOBLTHW:
return FALSE;
break;
default:break;
}
//BOOL bSucc = LoadToBackSurface( offScreenGraphics->GetSurface(), left, top, pRect );
if( srcRect == NULL )
SAFE_DELETE( pRect );
if( DD_OK == hr )
return TRUE;
return FALSE;
}
BOOL cDirectDraw::LoadToBackSurface( cGraphics* offScreenGraphics, int left, int top, int height, int width )
{
RECT rcSrc;
rcSrc.left = left;
rcSrc.top = top;
rcSrc.right = rcSrc.left + width;
rcSrc.bottom = rcSrc.top + height;
return LoadToBackSurface( offScreenGraphics, left, top, &rcSrc );
}
BOOL cDirectDraw::DrawAlpha( cGraphics* offScreenGraphics, int left, int top, LPRECT srcRect )
{
//在此进行矩形的合理性判断
if( left >= m_iWidth || top >= m_iHeight )
return FALSE;
if( left < 0 )
{
srcRect->left -= left;
srcRect->right -= left;
left = 0;
}
if( top < 0 )
{
srcRect->top -= top;
srcRect->bottom -= top;
top = 0;
}
if( srcRect->right - srcRect->left - m_iWidth >= 0 )
{
srcRect->right -= srcRect->right - srcRect->left - m_iWidth;
}
if( srcRect->bottom - srcRect->top - m_iHeight > 0 )
{
srcRect->bottom -= srcRect->bottom - srcRect->top - m_iHeight;
}
if( srcRect->right - srcRect->left <= 0 )
return FALSE;
if( srcRect->bottom - srcRect->top <= 0 )
return FALSE;
COLORREF gdiColorKey = RGB2GDIColor( offScreenGraphics->m_clrKey );
BYTE rKey = GetRValue(gdiColorKey);
BYTE gKey = GetGValue(gdiColorKey);
BYTE bKey = GetBValue(gdiColorKey);
DDSURFACEDESC2 ddsd;
memset( &ddsd, 0, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
m_lpDDS_Back->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
BYTE* pBack = (BYTE*)ddsd.lpSurface;
BYTE* p = (BYTE*)ddsd.lpSurface;
DDSURFACEDESC2 ddsd2;
memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
ddsd2.dwSize = sizeof(DDSURFACEDESC2);
offScreenGraphics->GetSurface()->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );
BYTE* pOff = (BYTE*)ddsd2.lpSurface;
BYTE* p2 = (BYTE*)ddsd2.lpSurface;
int pos1 = 0;
int pos2 = 0;
int t1=0,t2=0;
//move to the currect line
t1 = srcRect->top*ddsd2.lPitch;
t2 = top*ddsd.lPitch;
//32位色
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 )
{
//有透明色
if( offScreenGraphics->m_bColorKey )
{
for( int y=srcRect->top; y<srcRect->bottom; y++ )
{
pos1 = t1 + (srcRect->left<<2);
pos2 = t2 +(left<<2);
for( int x=srcRect->left; x<srcRect->right; x++ )
{
if( pOff[pos1] != bKey && pOff[pos1+1] != gKey && pOff[pos1+2] != rKey )//color key
{
pBack[pos2] = ( pBack[pos2] + pOff[pos1] )>>1;
pBack[pos2+1] = ( pBack[pos2+1] + pOff[pos1+1] )>>1;
pBack[pos2+2] = ( pBack[pos2+2] + pOff[pos1+2] )>>1;
}
pos1 += 4;//next pixel
pos2 += 4;
}
t1 += ddsd2.lPitch;//next line
t2 += ddsd.lPitch;
}
}
//无透明色
else
{
for( int y=srcRect->top; y<srcRect->bottom; y++ )
{
pos1 = t1 + (srcRect->left<<2);
pos2 = t2 +(left<<2);
for( int x=srcRect->left; x<srcRect->right; x++ )
{
pBack[pos2] = ( pBack[pos2] + pOff[pos1] )>>1;
pBack[pos2+1] = ( pBack[pos2+1] + pOff[pos1+1] )>>1;
pBack[pos2+2] = ( pBack[pos2+2] + pOff[pos1+2] )>>1;
pos1 += 4;//next pixel
pos2 += 4;
}
t1 += ddsd2.lPitch;//next line
t2 += ddsd.lPitch;
}
}
}
//16位色
else if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
{
}
offScreenGraphics->GetSurface()->Unlock( NULL );
m_lpDDS_Back->Unlock( NULL );
return TRUE;
}
BOOL cDirectDraw::DrawAlpha(cGraphics* offScreenGraphics, int left, int top )
{
LPRECT pRect = new RECT;
DDSURFACEDESC2 ddsd;
memset( &ddsd, 0, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
offScreenGraphics->GetSurface()->GetSurfaceDesc( &ddsd );
pRect->left = 0;
pRect->top = 0;
pRect->right = ddsd.dwWidth;
pRect->bottom = ddsd.dwHeight;
DrawAlpha( offScreenGraphics, left, top, pRect );
SAFE_DELETE( pRect );
return TRUE;
}
cGraphics* cDirectDraw::RotateImage( cGraphics** ppGrDest, cGraphics* pGrSrc, float arcAngle, COLORREF clrKey, BOOL bIsColorKey, int mode/* = 1*/ )
{
assert( pGrSrc != NULL );
/*Lock Source Surface*/
DDSURFACEDESC2 ddsdSrc;
memset( &ddsdSrc, 0, sizeof(DDSURFACEDESC2) );
ddsdSrc.dwSize = sizeof(DDSURFACEDESC2);
pGrSrc->GetSurface()->Lock( NULL, &ddsdSrc, DDLOCK_WAIT, NULL );
float cosA = cos( arcAngle );
float sinA = sin( arcAngle );
int H = ddsdSrc.dwHeight;
int W = ddsdSrc.dwWidth;
/*
以源图的中心为圆心旋转
srcX = yDest*sin + xDest*cos;
srcY = yDest*cos - xDest*sin;
destX = xSrc*cos - ySrc*sin;
destY = xSrc*sin + ySrc*cos;
源图上对角线上的点旋转后的新坐标的X差和Y差即是新图的高和宽
有2对可能的值
*/
int h1 = abs( (int)( H*cosA - W*sinA ) );
int w1 = abs( (int)( H*sinA - W*cosA ) );
int h2 = abs( (int)( H*cosA + W*sinA ) );
int w2 = abs( (int)( H*sinA + W*cosA ) );
/*计算新图的高和宽*/
int h,w;
if( h1 > h2 )
{
h = h1;
w = w1;
}
else
{
h = h2;
w = w2;
}
/*旋转圆心*/
int x1 = W>>1;//源图
int y1 = H>>1;
int x2 = w>>1;//新图
int y2 = h>>1;
/*Rotate*/
cGraphics* pGrDest = NULL;
if( ppGrDest == NULL )
{
pGrDest = new cGraphics( w, h );
}
else
{
pGrDest = *ppGrDest;
//Reset Image Size
DDSURFACEDESC2 ddsdDest;
memset( &ddsdDest, 0, sizeof(DDSURFACEDESC2) );
ddsdDest.dwSize = sizeof(DDSURFACEDESC2);
pGrDest->GetSurface()->GetSurfaceDesc( &ddsdDest );
ddsdDest.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT;
ddsdDest.dwHeight = h;
ddsdDest.dwWidth = w;
HRESULT hr = pGrDest->GetSurface()->SetSurfaceDesc( &ddsdDest, 0 );
/* return DDERR_INVALIDPARAMS
so let ppGrDest be NULL when use this function */
/* 这里执行失败,暂时还没有解决这个Bug */
int errCode = 0;
switch( hr )
{
case DDERR_INVALIDPARAMS:
errCode = 1;
break;
case DDERR_INVALIDOBJECT:
errCode = 2;
break;
case DDERR_SURFACELOST:
errCode = 3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -