1、初始化DirectDraw接口
#include <ddraw.h>
LPDIRECTDRAW m_lpDDraw;
LPDIRECTDRAWSURFACE m_lpDDSPrime;
LPDIRECTDRAWSURFACE m_lpDDSBack;
DDSURFACEDESC m_DDSdesc;
#pragma comment(lib, "ddraw.lib")
BOOL InitDDraw()
{
HRESULT hr = DirectDrawCreate(NULL, &m_lpDDraw, NULL);
if (FAILED(hr))
return FALSE;
hr = m_lpDDraw->SetCooperativeLevel(NULL, DDSCL_NORMAL);
if (FAILED(hr))
return FALSE;
DDSURFACEDESC DDSdesc;
ZeroMemory(&DDSdesc, sizeof(DDSdesc));
DDSdesc.dwSize = sizeof(DDSdesc);
DDSdesc.dwFlags = DDSD_CAPS;
DDSdesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hr = m_lpDDraw->CreateSurface(&DDSdesc, &m_lpDDSPrime, NULL);
if (FAILED(hr))
return FALSE;
ZeroMemory(&DDSdesc, sizeof(DDSdesc));
DDSdesc.dwSize = sizeof(DDSdesc);
DDSdesc.dwFlags = DDSD_ALL;
hr = m_lpDDSPrime->GetSurfaceDesc(&DDSdesc);
if (FAILED(hr))
return FALSE;
// 备份描述信息
memcpy(&m_DDSdesc, &DDSdesc, sizeof(DDSdesc));
DDSdesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
DDSdesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
hr = m_lpDDraw->CreateSurface(&DDSdesc, &m_lpDDSBack, 0);
if (FAILED(hr))
return FALSE;
return TRUE;
}
2、捕获屏幕数据
BOOL CaptureScreenImage(RECT &rcCapture, void *pData, INT &nLen)
{
if (m_lpDDSBack == NULL)
return FALSE;
HRESULT hr = m_lpDDSBack->BltFast(rcCapture.left, rcCapture.top, m_lpDDSPrime, &rcCapture, DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);
if (FAILED(hr))
return FALSE;
DDSURFACEDESC surfDesc;
ZeroMemory(&surfDesc, sizeof(surfDesc));
surfDesc.dwSize = sizeof(surfDesc);
hr = m_lpDDSBack->Lock(&rcCapture, &surfDesc, DDLOCK_READONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);
if (FAILED(hr))
return FALSE;
// 这里拷贝的是位深度为32位数据
memcpy(pData, (BYTE*)surfDesc.lpSurface, surfDesc.dwWidth * surfDesc.dwHeight * surfDesc.ddpfPixelFormat.dwRGBBitCount / 8);
m_lpDDSBack->Unlock(surfDesc.lpSurface);
return TRUE;
}
鉴于DirectDraw接口使用次数比较少,所以功能并没有并入到之前的屏幕捕获(GDI/DXGDI)统一接口中去。