How to make screenshot?

Yep. Picture of the screen.
btw can not see “Stream” method.

Check this out

http://xboxforums.create.msdn.com/forums/p/67895/414519.aspx

On some platforms you can use the SaveAsPng() method as pointed out in the article cited above. However, the function has not been implemented yet on Windows, so you can use the GraphicsDevice.SetRenderTarget() function and draw the scene again instead. Here is an example how to use it.

public Texture2D TakeScreenshot()
{
    int w, h;
    w = GraphicsDevice.PresentationParameters.BackBufferWidth;
    h = GraphicsDevice.PresentationParameters.BackBufferHeight;
    RenderTarget2D screenshot;
    screenshot = new RenderTarget2D(GraphicsDevice, w, h, false, SurfaceFormat.Bgra32, DepthFormat.None);
    GraphicsDevice.SetRenderTarget(screenshot);
    // _lastUpdatedGameTime is a variable typed GameTime, used to record the time last updated and create a common time standard for some game components
    Draw(_lastUpdatedGameTime != null ? _lastUpdatedGameTime : new GameTime());
    GraphicsDevice.Present();
    GraphicsDevice.SetRenderTarget(null);
    return screenshot;
}
public static void Save(this Texture2D texture, ImageFormat imageFormat, Stream stream)
{
    var width = texture.Width;
    var height = texture.Height;
    using (Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb))
    {
        IntPtr safePtr;
        BitmapData bitmapData;
        System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, width, height);

        texture.GetData(textureData);
        bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
        safePtr = bitmapData.Scan0;
        Marshal.Copy(textureData, 0, safePtr, textureData.Length);
        bitmap.UnlockBits(bitmapData);
        bitmap.Save(stream, imageFormat);

        textureData = null;
    }
    GC.Collect();
}

Well, the Save() function is optional, and it requires System.Drawing namespace.
Some of the work is inspired by this page. The code is copied from an article of my blog (the page is in Chinese).


BTW, don’t forget to manually Dispose() the Texture2D created by the TakeScreenshot() function.

The safest way to deal with this is to wrap the call to TakeScreenshot in a using block and to call the Save method in the using block’s body. This way, the Texture2D will always be disposed, regardless of what happens.

This solution does not work to me for new MonoGame releases, because due to this check that was introduced
`
public void Present()
{
// We cannot present with a RT set on the device.
if (_currentRenderTargetCount != 0)
throw new InvalidOperationException(“Cannot call Present when a render target is active.”);

        _graphicsMetrics = new GraphicsMetrics();
        PlatformPresent();
    }`

I get the exception. Someone has a suggestion to this?

Make sure you unset any render target before the end of your Draw method by calling GraphicsDevice.SetRenderTarget(null).

Thank you. That avoids the exception.

1 Like