📄 tddrawbase.cpp
字号:
}
//-----------------------------------------------------------------------------
TDDrawDisplay::~TDDrawDisplay()
{
DestroyObjects();
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::DestroyObjects()
{
SAFE_RELEASE( _BackBuffer );
SAFE_RELEASE( _FrontBuffer );
if(_DirectDraw)
_DirectDraw->SetCooperativeLevel( _hWindow, DDSCL_NORMAL );
SAFE_RELEASE(_DirectDraw);
return S_OK;
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::CreateFullScreenDisplay(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
{
DestroyObjects();
if(FAILED(DirectDrawCreateEx(NULL, (VOID**)&_DirectDraw, IID_IDirectDraw7, NULL)))
return E_FAIL;
if(FAILED(_DirectDraw->SetCooperativeLevel(_hWindow, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN)))
return E_FAIL;
if(FAILED(_DirectDraw->SetDisplayMode(dwWidth, dwHeight, dwBPP, 0, 0)))
return E_FAIL;
_ScrWidth = dwWidth;
_ScrHeight = dwHeight;
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 | DDSCAPS_3DDEVICE;
ddsd.dwBackBufferCount = 1; //Create primary surface (with backbuffer attached)
if(FAILED(_DirectDraw->CreateSurface(&ddsd, &_FrontBuffer, NULL)))
return E_FAIL;
DDSCAPS2 ddscaps;
ZeroMemory(&ddscaps, sizeof(ddscaps));
ddscaps.dwCaps = DDSCAPS_BACKBUFFER; //Get a pointer to the back buffer
if(FAILED(_FrontBuffer->GetAttachedSurface(&ddscaps, &_BackBuffer)))
return E_FAIL;
_BackBuffer->AddRef();
_bWindowed = false;
UpdateBounds();
return S_OK;
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::CreateWindowedDisplay(void)
{
DestroyObjects();
if(FAILED(DirectDrawCreateEx(NULL, (VOID**)&_DirectDraw, IID_IDirectDraw7, NULL)))
return E_FAIL;
if(FAILED(_DirectDraw->SetCooperativeLevel(_hWindow, DDSCL_NORMAL)))
return E_FAIL;
GetClientRect( _hWindow, &_WindowRect );
DDSURFACEDESC2 ddsd;
ZeroMemory( &ddsd, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; //Create the primary surface
if(FAILED(_DirectDraw->CreateSurface(&ddsd, &_FrontBuffer, NULL)))
return E_FAIL;
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; //Create the backbuffer surface
ddsd.dwWidth = _WindowRect.right - _WindowRect.left;
ddsd.dwHeight = _WindowRect.bottom - _WindowRect.top;
if(FAILED(_DirectDraw->CreateSurface(&ddsd, &_BackBuffer, NULL)))
return E_FAIL;
LPDIRECTDRAWCLIPPER pcClipper;
if(FAILED(_DirectDraw->CreateClipper(0, &pcClipper, NULL)))
return E_FAIL;
if(FAILED(pcClipper->SetHWnd( 0, _hWindow)))
{
pcClipper->Release();
return E_FAIL;
}
if(FAILED(_FrontBuffer->SetClipper(pcClipper)))
{
pcClipper->Release();
return E_FAIL;
}
pcClipper->Release();
_bWindowed = true;
UpdateBounds();
return S_OK;
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::Present()
{
HRESULT hr;
if((!_FrontBuffer) || (!_BackBuffer))
return E_POINTER;
while(1)
{
if(_bWindowed)
hr = _FrontBuffer->Blt(&_WindowRect, _BackBuffer, NULL, DDBLT_WAIT, NULL);
else
hr = _FrontBuffer->Flip(NULL, 0);
if(hr == DDERR_SURFACELOST)
{
_FrontBuffer->Restore();
_BackBuffer->Restore();
}
if(hr != DDERR_WASSTILLDRAWING)
return hr;
}
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette )
{
if((!_FrontBuffer) || (!_BackBuffer))
return E_POINTER;
if(pPalette)
_FrontBuffer->SetPalette( pPalette );
TDDrawSurface backBuffer(this);
backBuffer.Create(_BackBuffer);
if(FAILED(backBuffer.DrawBitmap(hbm, 0, 0, 0, 0)))
return E_FAIL;
return Present();
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::ColorKeyBlt(DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc)
{
if(!_BackBuffer)
return E_POINTER;
return _BackBuffer->BltFast(x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY);
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::Blt(DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, DWORD dwFlags)
{
if(!_BackBuffer)
return E_POINTER;
return _BackBuffer->BltFast(x, y, pdds, prc, dwFlags);
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::Blt(DWORD x, DWORD y, TDDrawSurface* pSurface, RECT* prc)
{
if(!pSurface )
return E_INVALIDARG;
if(pSurface->ColorKeyed)
return Blt(x, y, pSurface->DDrawSurface, prc, DDBLTFAST_SRCCOLORKEY);
else
return Blt(x, y, pSurface->DDrawSurface, prc, 0L);
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::Clear(DWORD dwColor)
{
if(!_BackBuffer)
return E_POINTER;
DDBLTFX ddbltfx;
ZeroMemory(&ddbltfx, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillColor = dwColor;
return _BackBuffer->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx);
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette )
{
if(!_FrontBuffer)
return E_POINTER;
return _FrontBuffer->SetPalette(pPalette);
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::CreatePaletteFromBitmap(LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP)
{
HRSRC hResource;
RGBQUAD* pRGB;
BITMAPINFOHEADER* pbi;
PALETTEENTRY aPalette[256];
HANDLE hFile;
DWORD iColor;
DWORD dwColors;
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
DWORD dwBytesRead;
if((!_DirectDraw) || (!strBMP) || (!ppPalette))
return E_INVALIDARG;
*ppPalette = NULL;
//Try to load the bitmap as a resource, if that fails, try it as a file
hResource = FindResource(NULL, strBMP, RT_BITMAP);
if(hResource)
{
pbi = (LPBITMAPINFOHEADER)LockResource(LoadResource(NULL, hResource));
if(!pbi)
return E_FAIL;
pRGB = (RGBQUAD*) ((BYTE*)pbi + pbi->biSize);
//Figure out how many colors there are
if(pbi == NULL || pbi->biSize<sizeof(BITMAPINFOHEADER))
dwColors = 0;
else if(pbi->biBitCount>8)
dwColors = 0;
else if(pbi->biClrUsed == 0)
dwColors = 1 << pbi->biBitCount;
else
dwColors = pbi->biClrUsed;
//A DIB color table has its colors stored BGR not RGB so flip them around.
for(iColor=0; iColor<dwColors; iColor++)
{
aPalette[iColor].peRed = pRGB[iColor].rgbRed;
aPalette[iColor].peGreen = pRGB[iColor].rgbGreen;
aPalette[iColor].peBlue = pRGB[iColor].rgbBlue;
aPalette[iColor].peFlags = 0;
}
return _DirectDraw->CreatePalette(DDPCAPS_8BIT, aPalette, ppPalette, NULL);
}
//Attempt to load bitmap as a file
bool bOK = false;
if((hFile=CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL))!=NULL)
{
ReadFile(hFile, &bf, sizeof(bf), &dwBytesRead, NULL); //Read the BITMAPFILEHEADER
if(dwBytesRead == sizeof(bf))
{
ReadFile(hFile, &bi, sizeof(bi), &dwBytesRead, NULL); //Read the BITMAPINFOHEADER
if(dwBytesRead == sizeof(bi))
{
ReadFile(hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL); //Read the PALETTEENTRY
if(dwBytesRead == sizeof(aPalette))
bOK = true;
}
}
CloseHandle( hFile );
}
if(!bOK)return E_FAIL;
//Figure out how many colors there are
if(bi.biSize != sizeof(BITMAPINFOHEADER))
dwColors = 0;
else if (bi.biBitCount > 8)
dwColors = 0;
else if (bi.biClrUsed == 0)
dwColors = 1 << bi.biBitCount;
else
dwColors = bi.biClrUsed;
//A DIB color table has its colors stored BGR not RGB so flip them around since DirectDraw uses RGB
for(iColor=0; iColor<dwColors; iColor++)
{
BYTE r = aPalette[iColor].peRed;
aPalette[iColor].peRed = aPalette[iColor].peBlue;
aPalette[iColor].peBlue = r;
}
return _DirectDraw->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL );
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::UpdateBounds()
{
if(_bWindowed)
{
GetClientRect(_hWindow, &_WindowRect);
ClientToScreen(_hWindow, (POINT*)&_WindowRect);
ClientToScreen(_hWindow, (POINT*)&_WindowRect+1);
}
else
{
SetRect(&_WindowRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
}
return S_OK;
}
//-----------------------------------------------------------------------------
HRESULT TDDrawDisplay::InitClipper()
{
LPDIRECTDRAWCLIPPER pClipper;
HRESULT hr;
//Create a clipper when using GDI to draw on the primary surface
if(FAILED(hr=_DirectDraw->CreateClipper(0, &pClipper, NULL)))
return hr;
pClipper->SetHWnd(0, _hWindow);
if(FAILED(hr=_FrontBuffer->SetClipper(pClipper)))
return hr;
//We can release the clipper now since g_pDDSPrimary now maintains a ref count on the clipper
SAFE_RELEASE(pClipper);
return S_OK;
}
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -