Archived

This topic is now archived and is closed to further replies.

1024B

How to capture a surface of a DirectX game?

Recommended Posts

There is a DirectX game running in exclusive mode, and I wan''t to capture the primary surface in my code.What to do? Print Screen is too slow, is there some "Direct" way? Thanks.

Share this post


Link to post
Share on other sites
I have successfully capture the primary surface of null-exclusive Directx application in this way:

Set my code to exclusive mode.
Create a primary surface.
Lock it.
Write to a DIB.

But this won''t work if it is a Directx game,since the game is in
exclusive mode.

Any idea?

Share this post


Link to post
Share on other sites

void CGraficos::GrabaScreenShot(char* NombreArchivo)
{
//Creamos un puntero al front buffer
IDirect3DSurface8* FrontBuffer;

//Extraemos las medidas del dispositivo
D3DVIEWPORT8 vp;
m_pD3DDevice->GetViewport(&vp);

//Ahora creamos la superficie en la que se copiara nuestra imagen
//La superfice del front buffer es D3DFMT_A8R8G8B8 cuando es regresada
m_pD3DDevice->CreateImageSurface(vp.Width, vp.Height, D3DFMT_A8R8G8B8, &FrontBuffer);

//Ahora copiamos el front buffer a nuestra superficie
HRESULT hr = m_pD3DDevice->GetFrontBuffer(FrontBuffer);

if(hr != D3D_OK)
{//Si fallo al obtener el front buffer
FrontBuffer->Release(); //Liberamos la superficie para evitar memory leaks
return;//Salimos de la funcion
}

//Ahora escribimos la informacion en un bitmap
D3DXSaveSurfaceToFile(NombreArchivo, D3DXIFF_BMP, FrontBuffer, NULL, NULL);

FrontBuffer->Release();
}

Share this post


Link to post
Share on other sites
Are you trying to grab a screenshot for your own app or anothers? NeonGE''s method works for your own app.

If you want to grab a screenshot of another app that''s currently running, try the following. You''ll probably want to change the Sleep to a hotkey usage but everything else will be the same:


#include <windows.h>

PBITMAPINFO CreateBitmapInfoStruct( HBITMAP hBmp );
void CreateBMPFile( LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC );

int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
Sleep(60000);

// HWND hWnd = GetForegroundWindow();
HWND hWnd = GetDesktopWindow();
if( hWnd ) {
RECT rW;
HDC hWC = GetDC(hWnd);
GetClientRect(hWnd, &rW);
if( hWC ) {
HDC hDC = CreateCompatibleDC(hWC);
if( hDC ) {
HBITMAP hBitmap = CreateCompatibleBitmap(hWC, rW.right, rW.bottom);
if( hBitmap ) {
HGDIOBJ hBMOld = SelectObject(hDC, hBitmap);
BitBlt(hDC, 0, 0, rW.right, rW.bottom, hWC, 0, 0, SRCCOPY);
PBITMAPINFO pBMI = CreateBitmapInfoStruct(hBitmap);
if( pBMI ) {
CreateBMPFile("screengrab.bmp", pBMI, hBitmap, hDC);
DeleteObject(hBitmap);
LocalFree(pBMI);
}
}
DeleteDC(hDC);
}
ReleaseDC(hWnd, hWC);
}
}
return 0;
}

//=============================================================================
PBITMAPINFO CreateBitmapInfoStruct( HBITMAP hBmp )
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;

// Retrieve the bitmap''s color format, width, and height.
GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp);

// Convert the color format to a count of bits.
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);

if( cClrBits == 1 ) cClrBits = 1;
else if( cClrBits <= 4 ) cClrBits = 4;
else if( cClrBits <= 8 ) cClrBits = 8;
else if( cClrBits <= 16 ) cClrBits = 16;
else if( cClrBits <= 24 ) cClrBits = 24;
else cClrBits = 32;

// Allocate memory for the BITMAPINFO structure. (This structure
// contains a BITMAPINFOHEADER structure and an array of RGBQUAD
// data structures.)

if( cClrBits < 24 )
pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * (1 << cClrBits));

// There is no RGBQUAD array for the 24 bpp or 32 bpp format.
else
pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));

// Initialize the fields in the BITMAPINFO structure.
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;

if( cClrBits < 24 )
// if( cClrBits < 16 )
pbmi->bmiHeader.biClrUsed = 1 << cClrBits;

// If the bitmap is not compressed, set the BI_RGB flag.
pbmi->bmiHeader.biCompression = BI_RGB;

// Compute the number of bytes in the array of color
// indices and store the result in biSizeImage.
pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) / 8
* pbmi->bmiHeader.biHeight*cClrBits;

// Set biClrImportant to 0, indicating that all of the
// device colors are important.
pbmi->bmiHeader.biClrImportant = 0;

return pbmi;
}

//=============================================================================
void CreateBMPFile( LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC )
{
HANDLE hf; // file handle
BITMAPFILEHEADER hdr; // bitmap file-header
PBITMAPINFOHEADER pbih; // bitmap info-header
LPBYTE lpBits; // memory pointer
DWORD dwTotal; // total count of bytes
DWORD cb; // incremental count of bytes
BYTE *hp; // byte pointer
DWORD dwTmp;

pbih = (PBITMAPINFOHEADER)pbi;
lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

// Retrieve the color table (RGBQUAD array) and the bits
// (array of palette indices) from the DIB.
if( pbih->biBitCount < 24 )
GetDIBits(hDC, hBMP, 0, (WORD)pbih->biHeight, lpBits, pbi, DIB_PAL_COLORS);
else
GetDIBits(hDC, hBMP, 0, (WORD)pbih->biHeight, lpBits, pbi, DIB_RGB_COLORS);

// Create the .BMP file.
hf = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, (DWORD) 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);

hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"

// Compute the size of the entire file.
hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed
* sizeof(RGBQUAD) + pbih->biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;

// Compute the offset to the array of color indices.
hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed
* sizeof(RGBQUAD);

// Copy the BITMAPFILEHEADER into the .BMP file.
WriteFile(hf, (LPVOID)&hdr, sizeof(BITMAPFILEHEADER), (LPDWORD)&dwTmp, NULL);

// Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
WriteFile(hf, (LPVOID)pbih, sizeof(BITMAPINFOHEADER) +
pbih->biClrUsed * sizeof(RGBQUAD), (LPDWORD)&dwTmp, NULL);

// Copy the array of color indices into the .BMP file.
dwTotal = cb = pbih->biSizeImage;
hp = lpBits;

WriteFile(hf, (LPSTR)hp, (int)cb, (LPDWORD)&dwTmp, NULL);

// Close the .BMP file.
CloseHandle(hf);

// Free memory.
GlobalFree((HGLOBAL)lpBits);
}

Share this post


Link to post
Share on other sites