1

I'm trying to copy a screenshot (bitmap) of a UWP UIElement to the clipboard, suitable for pasting into e.g. Paint.

Here's what I have so far:

        public async void CopyScreenshot(UIElement content)
        {
            DataPackage dataPackage = new();

            using (InMemoryRandomAccessStream stream = new())
            {
                await RenderContentToRasterStreamAsync(content, stream);
                stream.Seek(0);    
                
                dataPackage.SetBitmap(RandomAccessStreamReference.CreateFromStream(stream));  
            }

            try
            {
                Clipboard.SetContent(dataPackage);
                Data.AppStatusText = "Screenshot copied to clipboard.";
            }
            catch (Exception)
            {
                Data.AppStatusText = "Copying to clipboard failed.";
            }
        }

        private async Task RenderContentToRasterStreamAsync(UIElement content, IRandomAccessStream stream)
        {
            RenderTargetBitmap renderTargetBitmap = new();
            await renderTargetBitmap.RenderAsync(content);

            var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
            var pixels = pixelBuffer.ToArray();
            var displayInformation = DisplayInformation.GetForCurrentView();

            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                BitmapAlphaMode.Premultiplied,
                (uint)renderTargetBitmap.PixelWidth,
                (uint)renderTargetBitmap.PixelHeight,
                displayInformation.RawDpiX,
                displayInformation.RawDpiY,
                pixels);

            await encoder.FlushAsync();
        }

This code runs, but when attempting to paste the result I get the message:

"The information on the clipboard cannot be inserted into Paint".

The RenderContentToRasterStreamAsync method works as desired when I use it to save a picture of the UIElement to a file.

What do I need to change to copy to the clipboard? Thanks in advance.

Siyh
  • 1,747
  • 1
  • 17
  • 24

1 Answers1

1

Save screenshot of control to clipboard

Derive testing, it looks the stream comes from RenderContentToRasterStreamAsync has been closed before insert into the data package. During testing with official code sample, it could copy and pause image for Paint. Base on this thread, I have edited RenderContentToRasterStreamAsync1 thread and make the stream as return, then load it as bitmap. haha, It woks!

public async void CopyScreenshot1(UIElement content)
{
    DataPackage dataPackage = new DataPackage();
    var stream = await RenderContentToRasterStreamAsync1(content);
    dataPackage.SetBitmap(RandomAccessStreamReference.CreateFromStream(stream));

    try
    {
        Clipboard.SetContent(dataPackage);

    }
    catch (Exception)
    {

    }
}

private async Task<InMemoryRandomAccessStream> RenderContentToRasterStreamAsync1(UIElement content)
{
    RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
    await renderTargetBitmap.RenderAsync(content);

    var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
    var pixels = pixelBuffer.ToArray();
    var displayInformation = DisplayInformation.GetForCurrentView();

    var stream = new InMemoryRandomAccessStream();
    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
    encoder.SetPixelData(BitmapPixelFormat.Bgra8,
        BitmapAlphaMode.Premultiplied,
        (uint)renderTargetBitmap.PixelWidth,
        (uint)renderTargetBitmap.PixelHeight,
        displayInformation.RawDpiX,
        displayInformation.RawDpiY,
        pixels);

    await encoder.FlushAsync();

    return stream;
}
Nico Zhu
  • 32,367
  • 2
  • 15
  • 36