Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: DirectX VC++
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);
    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 12-Feb-13 20:43pm
Guru_C++1.2K
Comments
Guru_C++ at 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

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

Solution 1

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.
  Permalink  
Comments
Guru_C++ at 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 at 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++ at 13-Feb-13 6:42am
   
ok Thank you,.. I will check it out :)

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

  Print Answers RSS
0 OriginalGriff 584
1 Maciej Los 275
2 DamithSL 233
3 Sergey Alexandrovich Kryukov 209
4 BillWoodruff 200
0 OriginalGriff 6,803
1 Sergey Alexandrovich Kryukov 6,377
2 DamithSL 5,421
3 Manas Bhardwaj 4,841
4 Maciej Los 4,330


Advertise | Privacy | Mobile
Web04 | 2.8.1411023.1 | Last Updated 13 Feb 2013
Copyright © CodeProject, 1999-2014
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