不過可以使用.net Form的方法做到,先加入參考System.Drawing
Bitmap CaptureScreen()
{
/// new a bitmap with screen width and height
Bitmap b = new Bitmap(
(int)SystemParameters.PrimaryScreenWidth,
(int)SystemParameters.PrimaryScreenHeight);
/// copy screen through .net form api
using (Graphics g = Graphics.FromImage(b))
{
g.CopyFromScreen(0, 0, 0, 0,
b.Size, CopyPixelOperation.SourceCopy);
}
return b;
}
這時候得到的是Form使用的Bitmap物件
如果要存成圖檔的話就可以直接使用Bitmap物件的Save
void SaveBitmap(Bitmap b, string f)
{
b.Save(f);
}
或是再把它轉換成WPF使用的BitmapSource
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteObject(IntPtr hObject);
private static BitmapSource ToBitmapSource(Bitmap b)
{
/// transform to hbitmap image
IntPtr hb = b.GetHbitmap();
/// convert hbitmap to bitmap source
BitmapSource bs =
Imaging.CreateBitmapSourceFromHBitmap(
hb, IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
/// release temp hbitmap image
DeleteObject(hb);
return bs;
}
不過由於透明背景的視窗會被放在不同層的顯示記憶體中
這也造成了使用上面的捕捉畫面方法會抓不到透明的視窗
如果希望抓到的畫面包括這樣的視窗,那就要直接用Win32的GDI+函式了
const uint SRCCOPY = 0x00CC0020;
const uint CAPTUREBLT = 0x40000000;
[DllImport("user32.dll")]
static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool BitBlt(IntPtr hdcDest, int nXDest,
int nYDest, int nWidth, int nHeight, IntPtr hdcSrc,
int nXSrc, int nYSrc, uint dwRop);
[DllImport("user32.dll")]
static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
void CaptureScreen()
{
/// new a bitmap with screen width and height
Bitmap b = new Bitmap(
(int)SystemParameters.PrimaryScreenWidth,
(int)SystemParameters.PrimaryScreenHeight);
/// copy screen through gdi+ api
using (Graphics g = Graphics.FromImage(b))
{
IntPtr hdc = g.GetHdc();
IntPtr dh = GetDesktopWindow();
IntPtr dhdc = GetDC(dh);
BitBlt(hdc, 0, 0,
(int)SystemParameters.PrimaryScreenWidth,
(int)SystemParameters.PrimaryScreenHeight,
dhdc, 0, 0, SRCCOPY | CAPTUREBLT);
/// release and dispose unmanaged resources
ReleaseDC(dh, dhdc);
g.ReleaseHdc();
hdc = IntPtr.Zero;
dh = IntPtr.Zero;
}
}
這樣就可以抓到透明背景的視窗
但是如果仔細看的話會發現在抓圖的時候,滑鼠游標會有一個閃爍
(需要連續一直抓比較明顯,直接抓是看不太出來的)
這是因為透明圖層跟滑鼠游標是在同一層
但是BitBlt的原則是不要抓到滑鼠游標
所以會再抓取透明圖層的時候會先將滑鼠變不見
--
參考資料
ScreenShot Application in WPF using GD+
BitBlt (gdi32)
The Case of the Disappearing Cursor
沒有留言:
張貼留言