Đây là một (!!) lớn bưu điện, mặc dù với tất cả các ý kiến và đề nghị, nó đã cho tôi một giờ để tìm ra từng mảnh. Vì vậy, đây là một cuộc gọi để có được BitMapSource với SafeHandles, và sau đó một ví dụ sử dụng của nó để tạo ra một tập tin hình ảnh .PNG. Ở dưới cùng là 'sử dụng' và một số tài liệu tham khảo.Tất nhiên, không có tín dụng nào là của tôi, tôi chỉ là người ghi chép.
private static BitmapSource CopyScreen()
{
var left = Screen.AllScreens.Min(screen => screen.Bounds.X);
var top = Screen.AllScreens.Min(screen => screen.Bounds.Y);
var right = Screen.AllScreens.Max(screen => screen.Bounds.X + screen.Bounds.Width);
var bottom = Screen.AllScreens.Max(screen => screen.Bounds.Y + screen.Bounds.Height);
var width = right - left;
var height = bottom - top;
using (var screenBmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
{
BitmapSource bms = null;
using (var bmpGraphics = Graphics.FromImage(screenBmp))
{
IntPtr hBitmap = new IntPtr();
var handleBitmap = new SafeHBitmapHandle(hBitmap, true);
try
{
bmpGraphics.CopyFromScreen(left, top, 0, 0, new System.Drawing.Size(width, height));
hBitmap = screenBmp.GetHbitmap();
using (handleBitmap)
{
bms = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
} // using
return bms;
}
catch (Exception ex)
{
throw new ApplicationException($"Cannot CopyFromScreen. Err={ex}");
}
} // using bmpGraphics
} // using screen bitmap
} // method CopyScreen
Dưới đây là cách sử dụng, và cũng là lớp "Xử lý an toàn":
private void buttonTestScreenCapture_Click(object sender, EventArgs e)
{
try
{
BitmapSource bms = CopyScreen();
BitmapFrame bmf = BitmapFrame.Create(bms);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(bmf);
string filepath = @"e:\(test)\test.png";
using (Stream stm = File.Create(filepath))
{
encoder.Save(stm);
}
}
catch (Exception ex)
{
MessageBox.Show($"Err={ex}");
}
}
public class SafeHBitmapHandle : SafeHandleZeroOrMinusOneIsInvalid
{
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern int DeleteObject(IntPtr hObject);
[SecurityCritical]
public SafeHBitmapHandle(IntPtr preexistingHandle, bool ownsHandle)
: base(ownsHandle)
{
SetHandle(preexistingHandle);
}
protected override bool ReleaseHandle()
{
return DeleteObject(handle) > 0;
}
}
Và cuối cùng là một cái nhìn 'usings' của tôi:
using System;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Media.Imaging;
using System.Windows.Interop;
using System.Windows;
using System.IO;
using Microsoft.Win32.SafeHandles;
using System.Security;
Các DLL tham chiếu bao gồm: * PresentationCore * System.Core * System.Deployment * System.Drawing * Windo wsBase
Điều đó có hiệu quả. Có một chút bộ nhớ còn lại được tổ chức sau khi thử nghiệm, nhưng bộ thu gom rác sẽ nhặt nó lên. Cảm ơn Julien. –
Tuyệt vời. Bị kẹt giữa thư viện của bên thứ 3 và một nơi khó khăn. Điều này đã bình chọn nó. –
Đây là liên kết đến bài viết MSmap Bitmap.GetHBitmap nơi @JulienLebosquain đang trích dẫn từ http://msdn.microsoft.com/en-us/library/1dz311e4.aspx – Zack