摘要:WPF 抓取螢幕擷圖
在 MSDN 上看到 WPF 抓取螢幕擷圖的討論,
而原討論中的程式範例有 Memory leak 的問題,
因此我做了些修改。
新增一個 WPF 專案,
並將 System.Drawing 加入參考。
using System; // IntPtr
using System.Windows; // SystemParameters, Int32Rect
using System.Windows.Media.Imaging; // BitmapSource
using System.Drawing; // Bitmap, Graphics
using System.Windows.Interop; // Imaging
using System.Runtime.InteropServices; // DllImport
[DllImport("gdi32.dll")]
static extern IntPtr DeleteObject(IntPtr hDc);
static BitmapSource CopyScreen()
{
using (var screenBmp = new Bitmap((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
{
using (var bmpGraphics = Graphics.FromImage(screenBmp))
{
bmpGraphics.CopyFromScreen(0, 0, 0, 0, screenBmp.Size);
IntPtr hBitmap = screenBmp.GetHbitmap();
return Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
DeleteObject(hBitmap);
}
}
return bmpSource;
}
上面的例子是擷取整個主螢幕的畫面,
也可以擷取指定的螢幕範圍,修改如下:
static BitmapSource CopyScreen(int left, int top, int width, int height)
{
BitmapSource bmpSource;
using (var screenBmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
{
using (var bmpGraphics = Graphics.FromImage(screenBmp))
{
bmpGraphics.CopyFromScreen(left, top, 0, 0, screenBmp.Size, CopyPixelOperation.SourceCopy);
IntPtr hBitmap = screenBmp.GetHbitmap();
bmpSource = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
DeleteObject(hBitmap);
}
}
return bmpSource;
}
如果你在短時間內會大量擷取螢幕畫面(如每秒 30 次),
記得每次處理完後都要呼叫 GC.Collect() 強迫 CLR 回收記憶體,
否則很快就會 Out of Memory。