Does anybody have code they can share on how to do a screen capture using C#? Also is this feature going to be supported soon via API?
Screen captures are a problem on WP8. The only method available to you in C# is via Microsoft’s “System.Windows.Media.Imaging.WriteableBitmap” class, but unfortunately there is a bug on Microsoft’s end where it’ll fail to capture correctly if your app is also rendering to Direct3D via a DrawingSurfaceBackgroundGrid.
https://connect.microsoft.com/VisualStudio/feedback/details/785537/windows-phone-8-direct3d-xaml-application-writeablebitmap-render-bug
So, because of this WP8 bug on Microsoft’s end, the only way you can reliably capture the screen is to disable Corona’s rendering to the DrawingSurfaceBackgroundGrid. But if you do that, then your app will no longer be able to render at 60 FPS. Corona will then render to just under 30 FPS. This is a limitation in Microsoft Silverlight.
In my opinion, I think you should avoid screen capturing on WP8 for now. I think it’s more trouble than it’s worth. But if you’re willing to live with th limitation stated above, then here is an example on how to capture Corona’s screen content in C#. In this example, if you tap on the screen, the C# code will capture everything rendered to the CoronaPanel and display the captured image in the center of the app via a .NET “Image” control.
/// \<summary\>Constructor. Initializes member variables and the user interface.\</summary\> public MainPage() { // Initialize this page's components that were set up via the UI designer. InitializeComponent(); // Set up Corona to automatically start up when the control's Loaded event has been raised. // Note: By default, Corona will run the "main.lua" file in the "Assets\Corona" directory. // You can change the defaults via the CoronaPanel's AutoLaunchSettings property. fCoronaPanel.AutoLaunchEnabled = true; // You must disable rendering to the DrawingSurfaceBackgroundGrid in order to work-around a // Microsoft bug that prevents a WriteableBitmap from capturing the screen reliably. #if false // Set up the CoronaPanel control to render fullscreen via the DrawingSurfaceBackgroundGrid control. // This significantly improves the framerate and is the only means of achieving 60 FPS. fCoronaPanel.BackgroundRenderingEnabled = true; fDrawingSurfaceBackgroundGrid.SetBackgroundContentProvider(fCoronaPanel.BackgroundContentProvider); fDrawingSurfaceBackgroundGrid.SetBackgroundManipulationHandler(fCoronaPanel.BackgroundManipulationHandler); #endif // Add a Corona event handler which detects when the Corona project has been loaded, but not started yet. fCoronaPanel.Runtime.Loaded += OnRuntimeLoaded; } /// \<summary\> /// Called when a new CoronaRuntimeEnvironment has been created/loaded, /// but before the "main.lua" has been executed. /// \</summary\> /// \<param name="sender"\>The CoronaRuntime object that raised this event.\</param\> /// \<param name="e"\> /// Event arguments providing the CoronaRuntimeEnvironment that has been created/loaded. /// \</param\> private void OnRuntimeLoaded(object sender, CoronaLabs.Corona.WinRT.CoronaRuntimeEventArgs e) { e.CoronaRuntimeEnvironment.AddEventListener("tap", OnTapped); } /// \<summary\>Called when the user taps on the CoronaPanel and it wasn't handled in Lua.\</summary\> /// \<param name="sender"\>The CoronaRuntimeEnvironment that dispatched the event.\</param\> /// \<param name="e"\>Provides the Lua event table's fields/properties.\</param\> /// \<returns\>The value to be returned to Lua.\</returns\> private CoronaLabs.Corona.WinRT.ICoronaBoxedData OnTapped( CoronaLabs.Corona.WinRT.CoronaRuntimeEnvironment sender, CoronaLabs.Corona.WinRT.CoronaLuaEventArgs e) { // Capture the content of the CoronaPanel to a WriteableBitmap. var writeableBitmap = new System.Windows.Media.Imaging.WriteableBitmap( (int)fCoronaPanel.ActualWidth, (int)fCoronaPanel.ActualHeight); writeableBitmap.Render(fCoronaPanel, null); writeableBitmap.Invalidate(); // Display the captured image in the center of the screen. var imageView = new System.Windows.Controls.Image(); imageView.Source = writeableBitmap; imageView.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; imageView.VerticalAlignment = System.Windows.VerticalAlignment.Center; imageView.Width = fCoronaPanel.ActualWidth / 2; imageView.Height = fCoronaPanel.ActualHeight / 2; fCoronaPanel.Children.Add(imageView); // Return nil to Lua. return null; }
Is this feature going to be supported soon via the Corona Cards API? Also thanks for the code.
>> Is this feature going to be supported soon via the Corona Cards API?
Unfortunately no. Not in the near future.
Screen captures are a problem on WP8. The only method available to you in C# is via Microsoft’s “System.Windows.Media.Imaging.WriteableBitmap” class, but unfortunately there is a bug on Microsoft’s end where it’ll fail to capture correctly if your app is also rendering to Direct3D via a DrawingSurfaceBackgroundGrid.
https://connect.microsoft.com/VisualStudio/feedback/details/785537/windows-phone-8-direct3d-xaml-application-writeablebitmap-render-bug
So, because of this WP8 bug on Microsoft’s end, the only way you can reliably capture the screen is to disable Corona’s rendering to the DrawingSurfaceBackgroundGrid. But if you do that, then your app will no longer be able to render at 60 FPS. Corona will then render to just under 30 FPS. This is a limitation in Microsoft Silverlight.
In my opinion, I think you should avoid screen capturing on WP8 for now. I think it’s more trouble than it’s worth. But if you’re willing to live with th limitation stated above, then here is an example on how to capture Corona’s screen content in C#. In this example, if you tap on the screen, the C# code will capture everything rendered to the CoronaPanel and display the captured image in the center of the app via a .NET “Image” control.
/// \<summary\>Constructor. Initializes member variables and the user interface.\</summary\> public MainPage() { // Initialize this page's components that were set up via the UI designer. InitializeComponent(); // Set up Corona to automatically start up when the control's Loaded event has been raised. // Note: By default, Corona will run the "main.lua" file in the "Assets\Corona" directory. // You can change the defaults via the CoronaPanel's AutoLaunchSettings property. fCoronaPanel.AutoLaunchEnabled = true; // You must disable rendering to the DrawingSurfaceBackgroundGrid in order to work-around a // Microsoft bug that prevents a WriteableBitmap from capturing the screen reliably. #if false // Set up the CoronaPanel control to render fullscreen via the DrawingSurfaceBackgroundGrid control. // This significantly improves the framerate and is the only means of achieving 60 FPS. fCoronaPanel.BackgroundRenderingEnabled = true; fDrawingSurfaceBackgroundGrid.SetBackgroundContentProvider(fCoronaPanel.BackgroundContentProvider); fDrawingSurfaceBackgroundGrid.SetBackgroundManipulationHandler(fCoronaPanel.BackgroundManipulationHandler); #endif // Add a Corona event handler which detects when the Corona project has been loaded, but not started yet. fCoronaPanel.Runtime.Loaded += OnRuntimeLoaded; } /// \<summary\> /// Called when a new CoronaRuntimeEnvironment has been created/loaded, /// but before the "main.lua" has been executed. /// \</summary\> /// \<param name="sender"\>The CoronaRuntime object that raised this event.\</param\> /// \<param name="e"\> /// Event arguments providing the CoronaRuntimeEnvironment that has been created/loaded. /// \</param\> private void OnRuntimeLoaded(object sender, CoronaLabs.Corona.WinRT.CoronaRuntimeEventArgs e) { e.CoronaRuntimeEnvironment.AddEventListener("tap", OnTapped); } /// \<summary\>Called when the user taps on the CoronaPanel and it wasn't handled in Lua.\</summary\> /// \<param name="sender"\>The CoronaRuntimeEnvironment that dispatched the event.\</param\> /// \<param name="e"\>Provides the Lua event table's fields/properties.\</param\> /// \<returns\>The value to be returned to Lua.\</returns\> private CoronaLabs.Corona.WinRT.ICoronaBoxedData OnTapped( CoronaLabs.Corona.WinRT.CoronaRuntimeEnvironment sender, CoronaLabs.Corona.WinRT.CoronaLuaEventArgs e) { // Capture the content of the CoronaPanel to a WriteableBitmap. var writeableBitmap = new System.Windows.Media.Imaging.WriteableBitmap( (int)fCoronaPanel.ActualWidth, (int)fCoronaPanel.ActualHeight); writeableBitmap.Render(fCoronaPanel, null); writeableBitmap.Invalidate(); // Display the captured image in the center of the screen. var imageView = new System.Windows.Controls.Image(); imageView.Source = writeableBitmap; imageView.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; imageView.VerticalAlignment = System.Windows.VerticalAlignment.Center; imageView.Width = fCoronaPanel.ActualWidth / 2; imageView.Height = fCoronaPanel.ActualHeight / 2; fCoronaPanel.Children.Add(imageView); // Return nil to Lua. return null; }
Is this feature going to be supported soon via the Corona Cards API? Also thanks for the code.
>> Is this feature going to be supported soon via the Corona Cards API?
Unfortunately no. Not in the near future.