Click here to Skip to main content
15,886,825 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello Everyone..

Am new to this DirectX programming. Recently i have installed DirectX9 & setup with VS 2008. Am trying to take screenshot of Desktop ( client area i.e., not entire desktop, only specified region on desktop ). I've googled on this & found a peice of code.

C++
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>

IDirect3DDevice9* g_pd3dDevice;

int ScreenWidth = 100;
int ScreenHeight = 100;


void CaptureScreen()
{
    IDirect3DSurface9* pSurface;
    g_pd3dDevice->CreateOffscreenPlainSurface(ScreenWidth, ScreenHeight,
        D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
    g_pd3dDevice->GetFrontBufferData(0, pSurface);
    D3DXSaveSurfaceToFile("E:\\Desktop.bmp",D3DXIFF_BMP,pSurface,NULL,NULL);
    pSurface->Release(); 
}

void CDirectXProject::Screenshot()
{
  CaptureScreen();
}


And in Linker Properties -> Input I've refrenced d3d9.lib d3dx9.lib. In project folder, I've kept d3d9.dll, d3d9.lib & d3dx9.lib files.

But when i run the program, it crashes at CreateOffscreenPlainSurface function stating that Access violation. Am not getting what am doing wrong with this. And also i've specified the Image width & HEight. But how do i specify the client region i.e., x & y cordinate.
Please suggest me on this.

Thank you all..
Posted
Comments
Guru_C++ 13-Feb-13 2:42am    
I was able to figure out where is the problem, I came to know that I've not created the device. I changed the code like this:

// globals
LPDIRECT3D9 g_pDirect3D = NULL;
LPDIRECT3DDEVICE9 g_pDirect3D_Device = NULL;
IDirect3DDevice9* g_pd3dDevice ;

void CaptureScreen()
{
g_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);

D3DPRESENT_PARAMETERS PresentParams;
memset(&PresentParams, 0, sizeof(D3DPRESENT_PARAMETERS));

PresentParams.Windowed = TRUE;
PresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;

g_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL ,hMainWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING, &PresentParams,&g_pDirect3D_Device);

IDirect3DSurface9* pSurface;
g_pDirect3D_Device->CreateOffscreenPlainSurface(100, 100,
D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
g_pDirect3D_Device->GetFrontBufferData(0, pSurface);
D3DXSaveSurfaceToFile("E:\\Desktop.bmp",D3DXIFF_BMP,pSurface,NULL,NULL);
pSurface->Release();
}

This prevents the Access Violation error after creating the Device. But the Image is in black color. Am i missing it out somewhere.. Please point out me if am wrong..

1 solution

Hello.

1. Use system memory pool not scratch (D3DPOOL_SYSTEMMEM).
2. Instead of GetFronBufferData use GetBackBuffer and after call GetRenderTargetData of that surface - this way you get whole screen.
3. As you need part of the screen you can call D3DXLoadSurfaceFromSurface to copy part of the whole surface to your.
4. Another way is: to make a render target surface (RT) with resolution you need in default memory pool (POOL_DEFAULT) and call StretchRect method with region of interest - this way you will copy part of the screen into your surface but your surface on GPU in default memory pool so you should call GetRenderTargetData as already described.

Regards,
Maxim.
 
Share this answer
 
Comments
Guru_C++ 13-Feb-13 5:17am    
Hello Maxim, Thanks for replying.. I modified this code as per as your suggestion. The snippet code looks like this:

void ScreenShot()
{
IDirect3DDevice9* pDirect3DDevice;

IDirect3DSurface9* pRenderTarget=NULL;
IDirect3DSurface9* pDestTarget=NULL;

D3DDISPLAYMODE d3ddisplaymode;

D3DPRESENT_PARAMETERS PresentParams;
memset(&PresentParams, 0, sizeof(D3DPRESENT_PARAMETERS));

PresentParams.Windowed = TRUE;
PresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;

IDirect3D9* direct=Direct3DCreate9(D3D9b_SDK_VERSION);
direct->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
GetDesktopWindow(),
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&PresentParams,&pDirect3DDevice);

if (pDirect3DDevice == NULL)
return;

HRESULT hr = pDirect3DDevice->GetRenderTarget(0, &pRenderTarget);

hr = direct->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddisplaymode);

hr = pDirect3DDevice->CreateOffscreenPlainSurface(d3ddisplaymode.Width,d3ddisplaymode.Height,D3DFMT_A8R8G8B8,
D3DPOOL_SYSTEMMEM,
&pDestTarget,
NULL);

pDirect3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pDestTarget ) ;

hr = pDirect3DDevice->GetRenderTargetData(pRenderTarget,pDestTarget);

hr = D3DXSaveSurfaceToFile("E:\\abc.bmp",
D3DXIFF_BMP,
pDestTarget,
NULL,
NULL);

pRenderTarget->Release();
pDestTarget->Release();

}

But Still i use to get black image .. I dont know whats wrong is happening :(
Maxim Kartavenkov 13-Feb-13 5:35am    
You should read SDK documentation for the functions I mentioned.
The code you make totally wrong. You get backbuffer and after you should copy that data into your surface, but you are using same variable for all.
Guru_C++ 13-Feb-13 6:42am    
ok Thank you,.. I will check it out :)
pham michel 5-Jun-19 23:04pm    
what method you use for copy backbuffer data to surface
Maxim Kartavenkov 7-Jun-19 4:25am    
pDirect3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pDestTarget ) ;

hr = pDirect3DDevice->GetRenderTargetData(pRenderTarget,pDestTarget);

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900