Capture and draw a screenshot using directX

被刻印的时光 ゝ 提交于 2019-12-11 05:14:48

问题


I am trying to get DirectX (DX9) to grab a screenshot of the desktop and immediately draw it back out (in smaller dimensions) to my form.

I have DirectX working to the capacity that the device is created along with a few surfaces and I can render them to screen. I am using one surface F3F3Surf9_SS to get the desktop Screenshot.

Here is my declaration and initialization of varaibles

F3D3Surf9_SS : IDirect3DSurface9; //Surface SS
F3D3Surf9_A : IDirect3DSurface9;  //Surface A
F3D3Surf9_B : IDirect3DSurface9;  //Surface B

...

FDirect3D9.CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,Form1.Handle,
                        D3DCREATE_SOFTWARE_VERTEXPROCESSING,@D3DPresentParams,
                        FDirect3DDevice9);

FDirect3DDevice9.CreateOffscreenPlainSurface(1360,768,D3DFMT_X8R8G8B8,
                                             D3DPOOL_DEFAULT,F3D3Surf9_A,nil);

D3DXLoadSurfaceFromFile(F3D3Surf9_A,nil,nil,'D:\Images\Pillar.bmp',nil,
                        D3DX_DEFAULT,0,nil);

FDirect3DDevice9.CreateOffscreenPlainSurface(1360,768,D3DFMT_X8R8G8B8,
                                             D3DPOOL_DEFAULT,F3D3Surf9_B,nil);

D3DXLoadSurfaceFromFile(F3D3Surf9_B,nil,nil,'D:\Images\Niagra.bmp',nil,
                        D3DX_DEFAULT,0,nil);

FDirect3DDevice9.CreateOffscreenPlainSurface(Screen.Width,Screen.Height,D3DFMT_A8R8G8B8,
                                         D3DPOOL_SCRATCH,F3D3Surf9_SS,nil);

Here is the code I use to grab and then render the screenshot

FDIrect3DDevice9.BeginScene;

FDirect3DDevice9.Clear(0,0,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),0,0);
FDirect3DDevice9.GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO, BackBuffer);

FDirect3DDevice9.GetFrontBufferData(0,F3D3Surf9_SS);  //Get the screen shot

FDirect3DDevice9.StretchRect(F3D3Surf9_SS,nil,BackBuffer,nil,D3DTEXF_NONE); //Draw it

FDIrect3DDevice9.EndScene;
FDirect3DDevice9.Present(nil,nil,0,nil);

However this does not work.

The image does not get drawn to screen. If I draw surface A or B to screen, that works but it doesn't work for Surface SS. However I know Surface SS has the screenshot in it since if I call D3DXSaveSurfaceToFile the resulting bitmap I put on the hard disk is a valid screen shot.

Any thoughts on the proper way to do this?


回答1:


The reason this would not work is that the F3D3Surf9_SS was declared in system memory by D3DPOOL_SCRATCH and cannot be drawn directly to the back buffer as I was trying to.

So my solution was to use the F3D3Surf9_A surface and use UpdateSurface to copy the screenshot in system memory into the surface A in video memory.

The only other change I had to make to get this to work was create Surface A in the same format as the screenshot surface: D3DFMT_A8R8G8B8. Also had to make sure the the destination surface in UpdateSurface was larger than the source surface.

NOTE:

  • This is slow since we are reading from video memory to system memory and then right back to video memory.
  • I needed this for my application since I want to capture everything the OS and other application put on screen but if you are just worried about your own application then there are better alternatives.
  • If you know of a way to GetFrontBufferData without putting it to system memory (which is the only way I could see it working) please let me know.


来源:https://stackoverflow.com/questions/5518214/capture-and-draw-a-screenshot-using-directx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!