Ahh… screencaptures on WP8 Direct3D apps is a challenge. Which is why we don’t support it yet.
I don’t think a WriteableBitmap can capture what is custom Direct3D rendered to a DrawingSurfaceBackgroundGrid. I think the WriteableBitmap class can only capture what was rendered to a XAML control. (ie: Rendering via a DrawingSurfaceBackgroundGrid does not actually render to XAML, but gives us access to the app’s main Direct3D context which the native XAML framework uses to render its content.)
That said, capturing via a WriteableBitmap will work if you disable the CoronaPanel’s rendering to the DrawingSurfaceBackgroundGrid, because then it renders to a XAML SurfaceControl’s texture instead, which can be captured. The only problem with this is that you can’t render at 60 FPS when it is in this mode. But luckily we’ve set up our CoronaPanel to support hot-swapping between DrawingSurfaceBackgroundGrid and DrawingSurface rendering.
The following code successfully captures on the screen by doing what I’ve mentioned above. I consider it a hack though, but it’s the quickest thing I could come up with. The only problem is that you have to wait until the 2nd/3rd frame for the capture to occur.
private CoronaLabs.Corona.WinRT.CoronaLuaEventHandler fEnterFrameEventHandler = null; private int fEnterFrameCount = 0; private void OnCoronaRuntimeLoaded(object sender,CoronaRuntimeEventArgs e) { e.CoronaRuntimeEnvironment.AddEventListener("requestingScreenshot", OnRequestingScreenshot); } private ICoronaBoxedData OnRequestingScreenshot( CoronaRuntimeEnvironment sender, CoronaLuaEventArgs e) { // Switch from fast background rendering to rendering within the CoronaPanel. // We do this background rendered content is not capturable via WriteableBitmap. fCoronaPanel.BackgroundRenderingEnabled = false; // Schedule to capture the screen on the next rendered frame. if (fEnterFrameEventHandler == null) { fEnterFrameEventHandler = new CoronaLuaEventHandler(OnEnterFrame); } fEnterFrameCount = 0; sender.AddEventListener("enterFrame", fEnterFrameEventHandler); return null; } private ICoronaBoxedData OnEnterFrame( CoronaRuntimeEnvironment sender, CoronaLuaEventArgs e) { // The first frame still belongs to the background. Wait for the 2nd frame. fEnterFrameCount++; if (fEnterFrameCount \< 2) { return null; } // Remove the "enterFrame" event listener. // We don't want to capture the screen on every rendered frame. :) sender.RemoveEventListener("enterFrame", fEnterFrameEventHandler); // Capture the contents of the CoronaPanel. var writeableBitmap = new System.Windows.Media.Imaging.WriteableBitmap( (int)fCoronaPanel.ActualWidth, (int)fCoronaPanel.ActualHeight); writeableBitmap.Render(fCoronaPanel, null); writeableBitmap.Invalidate(); // As a quick test, display the captured image within an image control onscreen. var imageControl = new System.Windows.Controls.Image(); imageControl.Source = writeableBitmap; imageControl.Margin = new Thickness(50); fCoronaPanel.Children.Add(imageControl); // Re-enable fast 60 FPS background rendering. fCoronaPanel.BackgroundRenderingEnabled = true; return null; }