Hi there! I’ve been developing a small project, and wanted to know if there was any way to get the whole computer screen (Ex: if the game is windowed, I also want to get the person’s desktop) and copy it to a Texture2D.
Hi!
Sorry if I sound mean, but I was looking forward a method that involved the XNA framework itself.
Although if I don’t have any other choice, this is very interesting! Thanks!
I believe he wants to capture windows desktop and everything, not just what’s going on within the application. The kind of stuff you need when writing good ol’ Spyware/Trojan.
Long answer: if you know what underlying tech(directX, openGL, whatever) you’re using, it’s possible, but you lose all the the safety, portability, and ease of use a wrapper like monogame gets you along the way. For example, you can use SharpDX, the library monogame uses to interface with directx, to generate a separate direct3d device(presumably targeting device 0, who knows how many your user actually has), get the swapchain with ID zero on that device(may crash), get the backbuffers associated with that chain, do a resource copy on it, then change the usage parameters on the copy to allow read operations, stream the content out as bytes then convert those back to a monogame compatible texture2d.
//Dump the screen contents to a file
var width = GraphicsDevice.PresentationParameters.BackBufferWidth;
var height = GraphicsDevice.PresentationParameters.BackBufferHeight;
var colors = new Color[width * height];
GraphicsDevice.GetBackBufferData<Color>(colors);
using (var tex2D = new Texture2D(GraphicsDevice, width, height))
{
tex2D.SetData<Color>(colors);
using (var stream = File.Create(filename))
{
tex2D.SaveAsPng(stream, width, height);
}
}
oh, I just really read the question… nevermind. The answer to your question is No.
I have a working example, but you need to install a package to it, exactly System.Drawing.Common. You can easily download this within the project using NuGet.
Full code:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Screenshot
{
public class Game1 : Game
{
private GraphicsDeviceManager graphics;
private SpriteBatch spriteBatch;
System.Drawing.Bitmap bmp = null;
System.Drawing.Rectangle bounds;
System.Drawing.Graphics g;
int width,
height;
KeyboardState newState, oldState;
Texture2D texture;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
if (System.IO.Directory.Exists("Content") == false)
System.IO.Directory.CreateDirectory("Content");
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
}
void CaptureFullscreen()
{
width = GraphicsDevice.DisplayMode.Width;
height = GraphicsDevice.DisplayMode.Height;
bounds = new System.Drawing.Rectangle(0, 0, width, height);
bmp = new System.Drawing.Bitmap(bounds.Width, bounds.Height);
g = System.Drawing.Graphics.FromImage(bmp);
g.CopyFromScreen(new System.Drawing.Point(bounds.Left, bounds.Top), System.Drawing.Point.Empty, bmp.Size);
bmp.Save("Content/fullscreen.png", System.Drawing.Imaging.ImageFormat.Png);
System.IO.Stream s = new System.IO.FileStream("Content/fullscreen.png", System.IO.FileMode.Open);
texture = Texture2D.FromStream(GraphicsDevice, s);
s.Dispose();
}
void CaptureWindowscreen()
{
width = Window.ClientBounds.Width;
height = Window.ClientBounds.Height;
bounds = new System.Drawing.Rectangle(Window.ClientBounds.Left, Window.ClientBounds.Top, width, height);
bmp = new System.Drawing.Bitmap(bounds.Width, bounds.Height);
g = System.Drawing.Graphics.FromImage(bmp);
g.CopyFromScreen(new System.Drawing.Point(bounds.Left, bounds.Top), System.Drawing.Point.Empty, bmp.Size);
bmp.Save("Content/windowscreen.png", System.Drawing.Imaging.ImageFormat.Png);
}
protected override void Update(GameTime gameTime)
{
newState = Keyboard.GetState();
if (newState.IsKeyDown(Keys.Escape) && oldState.IsKeyUp(Keys.Escape))
Exit();
if (newState.IsKeyDown(Keys.F) && oldState.IsKeyUp(Keys.F))
CaptureFullscreen();
else if (newState.IsKeyDown(Keys.W) && oldState.IsKeyUp(Keys.W))
CaptureWindowscreen();
oldState = newState;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
if (texture != null)
spriteBatch.Draw(texture, new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
The saved images are placed in the Content folder, which is where the game was compiled. Just press W to save the window and F to save the full screen. You can view the full screen version immediately in the game window. Keep in mind that with this solution, if the game window protrudes somewhere on the screen, that part will not be saved, i.e. it will have a transparent texture. I don’t know what it produces with multiple displays, I only have one display.