В моем приложении winforms я хочу разрешить пользователю копировать снимок экрана компонента Bing Maps в буфер обмена (по крайней мере).

Я нашел следующий код из здесь, что выходит за рамки этого, но не компилируется для меня.

SaveScreenshot(this.userControl11.myMap, "MapScreenshot.png"); // code in menu item click handler

private async void SaveScreenshot(FrameworkElement captureSource, string suggestedName)
{
    //Create a FileSavePicker.
    var savePicker = new Windows.Storage.Pickers.FileSavePicker()
    {
        DefaultFileExtension = ".png",
        SuggestedFileName = suggestedName,
        SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary
    };

    savePicker.FileTypeChoices.Add(".png", new System.Collections.Generic.List<string> { ".png" });

    //Prompt the user to select a file.
    var saveFile = await savePicker.PickSaveFileAsync();

    //Verify the user selected a file.
    if (saveFile != null)
    {                
        using (var fileStream = await saveFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
        {
            //Capture the screenshot and save it to the file stream.
            await ScreenshotToStreamAsync(captureSource, fileStream);
        }
    }
}

private async Task ScreenshotToStreamAsync(FrameworkElement element, IRandomAccessStream stream)
{
    var renderTargetBitmap = new Windows.UI.Xaml.Media.Imaging.RenderTargetBitmap();
    await renderTargetBitmap.RenderAsync(element);

    var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();

    var dpi = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi;

    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
    encoder.SetPixelData(
        BitmapPixelFormat.Bgra8,
        BitmapAlphaMode.Ignore,
        (uint)renderTargetBitmap.PixelWidth,
        (uint)renderTargetBitmap.PixelHeight,
        dpi,
        dpi,
        pixelBuffer.ToArray());

    await encoder.FlushAsync();
}

Сообщение об ошибке времени компиляции, которое я получаю, касается IRandomAccessStream:

1>C:\Users\bclay\source\repos\MyMaps\MyMaps\Form1.cs(394,78,394,97): error CS0246: The type or namespace name 'IRandomAccessStream' could not be found (are you missing a using directive or an assembly reference?)

Итак, я нашел это , который указывает на то, что мне нужно "использовать" Windows.Storage.Streams;

... но когда я добавляю это, мне говорят, что пространство имен "Windows" не может быть найдено:

1>C:\Users\bclay\source\repos\MyMaps\MyMaps\Form1.cs(8,7,8,14): error CS0246: The type or namespace name 'Windows' could not be found (are you missing a using directive or an assembly reference?)

Что мне нужно сделать / изменить / добавить, чтобы это работало на Winforms? Или в моем случае нужен совсем другой подход?

0
B. Clay Shannon 22 Фев 2021 в 02:38

1 ответ

Лучший ответ

Есть несколько способов сделать это.

В качестве простого (но определенно не идеального) варианта вы можете использовать Graphics.FromScreen, чтобы скопировать часть экрана в графический объект:

var r = elementHost1.ClientRectangle;
using (var img = new Bitmap(r.Width, r.Height))
{
    using (var g = Graphics.FromImage(img))
    {
        var sr = elementHost1.RectangleToScreen(r);
        g.CopyFromScreen(sr.Location, System.Drawing.Point.Empty, sr.Size);
    }
    System.Windows.Forms.Clipboard.SetImage(img);
}

Другой вариант - использовать RenderTargetBitmap и PngBitmapEncoder, чтобы экспортировать его в изображение следующим образом:

public System.Drawing.Image DrawToImage(
    System.Windows.Controls.Control target)
{
    var rtb = new System.Windows.Media.Imaging.RenderTargetBitmap(
        (int)(target.ActualWidth), (int)(target.ActualHeight),
            96, 96, System.Windows.Media.PixelFormats.Pbgra32);
    rtb.Render(target);
    System.Windows.Media.Imaging.PngBitmapEncoder encoder =
        new System.Windows.Media.Imaging.PngBitmapEncoder();
    encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(rtb));
    var ms = new System.IO.MemoryStream();
    encoder.Save(ms);
    return System.Drawing.Image.FromStream(ms);
}

Затем вы можете поместить его в буфер обмена:

using (var image = DrawToImage(userControl11.myMap))
    System.Windows.Forms.Clipboard.SetImage(image);

Или сохраните его в файл:

using (var image = DrawToImage(userControl11.myMap))
    image.Save(@"c:\test\map.png", System.Drawing.Imaging.ImageFormat.Png);
1
Reza Aghaei 25 Фев 2021 в 02:26