Written By Microsoft MVP: Eric DeBrosse
In this article, I will explain how to save a screen shot from a Visual Basic 6 Direct3D8 application. This could be difficult to figure out on your own, since the VB SDK documentation does not mention the SaveSurfaceToFile method of the D3DX8 class. One thing that seems to cause confusion is the SrcPalette parameter. Even if you are not using indexed colors, you must still pass an un-initialized PALETTEENTRY structure to the SaveSurfaceToFile function. Passing Nothing will cause the function to fail.
Have a look at a simple function:

Public Sub SaveScreenShot(ByVal sFilename As String)
Dim oSurface As Direct3DSurface8
Dim SrcRect As RECT

'get display dimensions
g_oDevice.GetDisplayMode DispMode

'create a surface to put front buffer on,
'GetFrontBuffer always returns D3DFMT_A8R8G8B8
Set oSurface = g_oDevice.CreateImageSurface(DispMode.Width, _
DispMode.Height, _

'get data from front buffer
g_oDevice.GetFrontBuffer oSurface

'we are saving entire area of this surface
With SrcRect
.Left =
.Right = DispMode.Width
.Top =
.Bottom = DispMode.Height
End With

'save this surface to a BMP file
g_oD3DX.SaveSurfaceToFile sFilename, _
oSurface, _
SrcPalette, _
End Sub

The above function assumes g_oDevice is a valid Direct3DDevice8 object and g_oD3DX is a valid D3DX8 object.
First, we need to get the dimensions of the screen. If we were to use the GetViewport method to get the dimensions, it would fail on a device created with the D3DCreate_PUREDEVICE flag. Since GetFrontBuffer() always needs an image surface the size of the screen, (even when in windowed mode) the GetDisplayMode method is used and should not be an issue with pure devices.
Next, we create a new surface using the dimensions of our screen. The surface should be created using the D3DFMT_A8R8G8B8 format, because the GetFrontBuffer method always returns this format; regardless of the current back buffer format. We are using the GetFrontBuffer method to capture our screen shot, since it is the only way to capture anti-aliased output. The final call to SaveSurfaceToFile writes the entire captured surface to the specified bitmap file.
Notes: This function does not check for any errors! You should always set up some kind of error trap in any DirectX application, it makes it so much easier to debug. You could, for instance, validate the path and filename before actually trying to save the file. The function could also be easily modified to return a result code.