Friday, November 26, 2010

WP7 – Screen Capture on Device

One of the biggest features that I miss as a developer/blogger on the Windows Phone 7 device is the ability to take a screen shot.

The saving grace is that it is extremely easy to add code to your app so as to be able to capture the screen and save it to your album. Once the image has been saved, you can upload it to SkyDrive or to your computer via a Sync operation. (This is better than storing it to isolated storage, as that makes it harder to get at the image).

Here is the code:

using System.Windows.Media.Imaging;
using Microsoft.Advertising.Mobile.UI;
using Microsoft.Phone.Controls;
using Microsoft.Xna.Framework.Media;
using System.IO;

public static class Utility
/// <summary>
/// Currently supported only on the device. (Does not do anything while running with the emulator)
/// Will throw an exception if called while the device is connected to the computer (tethered mode)
/// so dont do that!
/// </summary>
/// <param name="page">the page whose screen shot needs to be captured</param>
/// <param name="saveName">the name that the image should be saved under - the device seems to ignore this parameter
/// and hence its ok to call this method with the same name multiple times, each image is stored separately</param>
/// <param name="quality">the jpeg image quality parameter</param>
/// <returns>A picture object representing the image</returns>
public static Picture DoCapture(this PhoneApplicationPage page, string saveName, int quality)
//first save to bitmap
WriteableBitmap bmp = new WriteableBitmap((int)page.ActualWidth, (int)page.ActualHeight);
bmp.Render(page, null);

//get memoryStream from bitmap and save to media library
Picture picture = null;
using (MemoryStream memoryStream = new MemoryStream())
bmp.SaveJpeg(memoryStream, bmp.PixelWidth, bmp.PixelHeight, 0, quality);
MediaLibrary mediaTest = new MediaLibrary();

memoryStream.Seek(0, SeekOrigin.Begin);
//name cannot be empty or null
//by default image gets saved to the album "Saved Pictures"
//SavePicture will throw an exception if called while the device is tethered
picture = mediaTest.SavePicture(saveName, memoryStream);
return picture;

And here is one method to call it from one of your application’s pages:

private void ApplicationBarCaptureButton_Click(object sender, EventArgs e)
Picture picture = this.DoCapture("Stocks 50-200.jpg",95);
MessageBox.Show("Screen capture saved: " + picture.Album + " " + picture.Name, "Screen Captured",
catch (Exception exp)
MessageBox.Show(exp.Message, "Error saving screen", MessageBoxButton.OK);

Something to notice is that as DoCapture was defined as an extension method, I am able to call it using the following syntax: this.DoCapture.

And here is what a saved screen-shot looks like (taken from my WP7 App – Stocks 50-200):


1 comment:

el_ber said...

Hi, I can't get the screen capture code to compile.

I get an error on:
Picture picture = this.DoCapture("Stocks 50-200.jpg", 95);
--> Number of arguments incorrect, or cannot convert MyGame.Game1 to Microsoft.Phone.Controls.PhoneApplication Page.

Where do you define the PhoneApplicationPage variable? How do I fix this?