Click here to Skip to main content
11,928,919 members (50,063 online)
Rate this:
Please Sign up or sign in to vote.
See more: DirectX VisualC++
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.

#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);
void CDirectXProject::Screenshot()

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 12-Feb-13 20:43pm
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);

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,
g_pDirect3D_Device->GetFrontBufferData(0, pSurface);

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

Rate this: bad
Please Sign up or sign in to vote.

Solution 1


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.

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;

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

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

IDirect3D9* direct=Direct3DCreate9(D3D9b_SDK_VERSION);

if (pDirect3DDevice == NULL)

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

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

hr = pDirect3DDevice->CreateOffscreenPlainSurface(d3ddisplaymode.Width,d3ddisplaymode.Height,D3DFMT_A8R8G8B8,

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

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

hr = D3DXSaveSurfaceToFile("E:\\abc.bmp",



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 :)
Member 11806482 8-Jul-15 4:00am
I am also trying to write a screencapture application.
I hope you figured out how to get rid of the black screen by now.
[Here]( is a link to my problem. I am presently using GetFrontBufferData. If the solution given above worked for you please let me know.
Maxim Kartavenkov 8-Jul-15 10:50am
Create destination surface in system memory pool instead of scratch.
Member 11806482 8-Jul-15 14:12pm
So I should change d3ddev->CreateOffscreenPlainSurface(screenW, screenH, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL); to d3ddev->CreateOffscreenPlainSurface(screenW, screenH, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface, NULL); ?

I also changed it to
d3ddev->CreateOffscreenPlainSurface(screenW, screenH, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pSurface, NULL);

I did this. But it is still returning a black screen. I apologize if I am sounding novice and I interpreted your solution incorrectly. I am new to DirectX programming.
Member 11806482 8-Jul-15 14:49pm
I also changed my code to this:

void captureScreenD3d()
UINT screenW = GetSystemMetrics(SM_CXSCREEN);
UINT screenH = GetSystemMetrics(SM_CYSCREEN);

IDirect3DSurface9* pbackBuffer;
d3ddev->CreateOffscreenPlainSurface(screenW, screenH, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pbackBuffer, NULL);

d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pbackBuffer);

D3DXSaveSurfaceToFile(L"screen.bmp", D3DXIFF_BMP, pbackBuffer, NULL, NULL);


Now it returns a black screen for every application, not just fullscreen games. Initial GetFrontBuffer worked fine for everything else. Just returned blackscreen for fullscreen games.
What am I doing wrong here?
Maxim Kartavenkov 9-Jul-15 12:03pm
Sure your code will not work.
You are even not even read mine answer, but asking the same!!!
You are not copy back buffer data to your surface in your code.

1. Create Device with the ARGB32 back buffer format.
2. Create offscreen surface not with the resolution which you take from GDI but from the back buffer resolution (they can be not the same)
3. Get back buffer surface and copy to your surface
4. Save surface into a file.


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

  Print Answers RSS
Top Experts
Last 24hrsThis month

Advertise | Privacy | Mobile
Web02 | 2.8.151126.1 | Last Updated 13 Feb 2013
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100