WPF 抓取螢幕擷圖

  • 1022
  • 0
  • 2013-07-01

摘要: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。