如何将我的 Bing 地图图像的屏幕截图复制到 Winforms 中的剪贴板?
How can I copy a screenshot of my Bing Maps image to the Clipboard in Winforms?
在我的 winforms 应用程序中,我希望允许用户将 Bing 地图组件的屏幕截图复制到剪贴板(至少)。
我从 here 中找到了以下代码,它超出了这个范围,但它没有为我编译。
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?)
所以我找到了this,说明我需要的“using”是using 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?)
我需要 do/change/add 什么才能让它在 Winforms 上运行?还是我的情况需要完全不同的方法?
有几种方法可以做到。
作为一个简单(但绝对不是完美)的选项,您可以使用 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 and 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);
在我的 winforms 应用程序中,我希望允许用户将 Bing 地图组件的屏幕截图复制到剪贴板(至少)。
我从 here 中找到了以下代码,它超出了这个范围,但它没有为我编译。
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?)
所以我找到了this,说明我需要的“using”是using 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?)
我需要 do/change/add 什么才能让它在 Winforms 上运行?还是我的情况需要完全不同的方法?
有几种方法可以做到。
作为一个简单(但绝对不是完美)的选项,您可以使用 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 and 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);