PDA

View Full Version : Screenshots



Magos
02-14-2003, 11:47 AM
Not sure whether this goes in GD or tech board. Anyway...

I'm working on a game, DirectDraw (fullscreen). I want to take a screenshot of some frames, however it doesn't work using PrintScreen (Ctrl+PS, Shift+PS, tried all combos...) nor any screenshot capture programs I've tried. I believe that DirectInput, which I'm also using, somehow prevents PrintScreen commands.
I have another DX program without DInput and PrintScreen works with it.
Does anyone have any idea how I could take a snapshot?

ober
02-14-2003, 12:36 PM
with a camera? :p

:: ducks for cover ::

Sang-drax
02-14-2003, 12:41 PM
It shouldn't be too hard to copy the pixel data to a file and add the appropriate bitmap header.
Use google to find the documentation of the .bmp format.

jdinger
02-14-2003, 01:22 PM
Magos,
Here's the code I use. It's almost straight out of MSDN, just a few modifications that I made (like the typedef, etc.). All you have to do is add the files to your project, include the header file in you main file and whenever you want to take a screenshot (like when a state in your DirectInput code is updated) pass your backbuffer into the SaveScreen function.

Of course, you could modify it to use unique filenames, like with an incrimental counter that adds a number to the end of the filename or something, but I didn't have a need for it so I never implemented it.
Hope this helps,

Jason



//in the header file, screencapture.h
#pragma once

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

typdef LPDIRECTDRAWSURFACE7 lpdds7;

void SaveScreen(lpdds7 sfHDC);
PBITMAPINFO MakeBI(lpdds7 sfHDC);




//in the source file, screencapture.cpp
#include "ScreenCapture.h"

HBITMAP NewBmp=NULL, OldBmp=NULL;
HDC hdcCom=NULL;

void SaveScreen(lpdds7 sfHDC)
{
HANDLE hf;
BITMAPFILEHEADER hdr;
PBITMAPINFOHEADER pbih;
LPBYTE lpBits;
DWORD dwTotal;
DWORD cb;
BYTE *hp;
DWORD dwTmp;
PBITMAPINFO pbiTest=MakeBI(sfHDC);
pbih=(PBITMAPINFOHEADER) pbiTest;
lpBits=(LPBYTE)GlobalAlloc(GMEM_FIXED,pbih->biSizeImage);
GetDIBits(hdcCom,NewBmp,0,(WORD)pbih->biHeight,lpBits,pbiTest,DIB_RGB_COLORS);
hf=CreateFile("screen.bmp",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE _NORMAL,NULL);
hdr.bfType=0x4d42;
hdr.bfSize=(DWORD)(sizeof(BITMAPFILEHEADER)+pbih->biSize+pbih->biClrUsed*sizeof(RGBQUAD)+pbih->biSizeImage);
hdr.bfReserved1=0;
hdr.bfReserved2=0;
hdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+pbih->biSize+pbih->biClrUsed*sizeof(RGBQUAD);
WriteFile(hf,(LPVOID)&hdr,sizeof(BITMAPFILEHEADER),(LPDWORD)&dwTmp,NULL);
WriteFile(hf,(LPVOID)pbih,sizeof(BITMAPINFOHEADER) +pbih->biClrUsed*sizeof(RGBQUAD),(LPDWORD)&dwTmp,NULL);
dwTotal=cb=pbih->biSizeImage;
hp=lpBits;
WriteFile(hf,(LPSTR)hp,(int)cb,(LPDWORD)&dwTmp,NULL);
CloseHandle(hf);
AddDebugLogEntry("Screen capture recorded.",0,1);
GlobalFree((HGLOBAL)lpBits);
SelectObject(hdcCom,OldBmp);
DeleteObject(NewBmp);
NewBmp=NULL;
DeleteDC(hdcCom);
hdcCom=NULL;
}

PBITMAPINFO MakeBI(lpdds7 sfHDC)
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
HDC hdc;
sfHDC->GetDC(&hdc);
NewBmp=CreateCompatibleBitmap(hdc,800,600);
hdcCom=CreateCompatibleDC(hdc);
OldBmp=(HBITMAP)SelectObject(hdcCom,NewBmp);
BitBlt(hdcCom,0,0,800,600,hdc,0,0,SRCCOPY);
sfHDC->ReleaseDC(hdc);
hdc=NULL;
GetObject(NewBmp,sizeof(BITMAP),(LPSTR)&bmp);
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;
if(cClrBits!=24)
pbmi=(PBITMAPINFO)LocalAlloc(LPTR,sizeof(BITMAPINF OHEADER)+sizeof(RGBQUAD)*(1<<cClrBits));
else
pbmi=(PBITMAPINFO)LocalAlloc(LPTR,sizeof(BITMAPINF OHEADER));
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)
pbmi->bmiHeader.biClrUsed=(1<<cClrBits);
pbmi->bmiHeader.biClrImportant=BI_RGB;
pbmi->bmiHeader.biSizeImage=((pbmi->bmiHeader.biWidth*cClrBits+31)&~31)*pbmi->bmiHeader.biHeight;
pbmi->bmiHeader.biClrImportant=0;
return(pbmi);
}

jdinger
02-14-2003, 01:25 PM
Oops. Sorry I just realized this wasn't commented **hides in shame**. If you want I can comment it to help you understand it better. Just let me know.

***EDIT**** also you need to include ddraw.h in the header.

Magos
02-14-2003, 02:39 PM
Thanks for the code. Don't bother posting the comments, I figured it out how it worked (actually, I made some modifications, shortening the code... :p).

Anyway, it worked perfectly on the first run. That rarely happens :D.

jdinger
02-14-2003, 02:54 PM
Originally posted by Magos
Thanks for the code. Don't bother posting the comments, I figured it out how it worked (actually, I made some modifications, shortening the code... :p).

Anyway, it worked perfectly on the first run. That rarely happens :D.

hehe...Glad to help. I just noticed that I left some stuff in that is specific to my engine like:



AddDebugLogEntry("Screen capture recorded.",0,1);


Glad to see you were able to clean it up and get it to work without any trouble. :D

frenchfry164
02-14-2003, 06:00 PM
doesn't GDI have a function that will take a screenshot?