通过处理捕获窗口的屏幕

我试图在桌面上只捕获一个特定的窗口,但我得到一个混合的图像,窗口和部分桌面区域的一部分。

我错过了什么?

这是我的代码:

RECT rect = new RECT(); if (!SetForegroundWindow(handle)) throw new Win32Exception(Marshal.GetLastWin32Error()); if (!GetWindowRect(handle, out rect)) throw new Win32Exception(Marshal.GetLastWin32Error()); Thread.Sleep(500); Rectangle windowSize = rect.ToRectangle(); Bitmap target = new Bitmap(windowSize.Width, windowSize.Height); using (Graphics g = Graphics.FromImage(target)) { g.CopyFromScreen(0, 0, 0, 0, new Size(windowSize.Width, windowSize.Height)); } target.Save("foo.png", System.Drawing.Imaging.ImageFormat.Png); 

Solutions Collecting From Web of "通过处理捕获窗口的屏幕"

我认为你的代码中的问题是这一行:

 g.CopyFromScreen(0, 0, 0, 0, new Size(windowSize.Width, windowSize.Height)); 

它应该是:

 g.CopyFromScreen(windowSize.X, windowSize.Y, 0, 0, new Size(windowSize.Width, windowSize.Height)); 

这是我个人用来获取特定窗口图像的方法 – 它可能派上用场:

 public Bitmap GetScreenshot() { IntPtr hwnd = ihandle;//handle here RECT rc; Win32.GetWindowRect(new HandleRef(null, hwnd), out rc); Bitmap bmp = new Bitmap(rc.Right - rc.Left, rc.Bottom - rc.Top, PixelFormat.Format32bppArgb); Graphics gfxBmp = Graphics.FromImage(bmp); IntPtr hdcBitmap; try { hdcBitmap = gfxBmp.GetHdc(); } catch { return null; } bool succeeded = Win32.PrintWindow(hwnd, hdcBitmap, 0); gfxBmp.ReleaseHdc(hdcBitmap); if (!succeeded) { gfxBmp.FillRectangle(new SolidBrush(Color.Gray), new Rectangle(Point.Empty, bmp.Size)); } IntPtr hRgn = Win32.CreateRectRgn(0, 0, 0, 0); Win32.GetWindowRgn(hwnd, hRgn); Region region = Region.FromHrgn(hRgn);//err here once if (!region.IsEmpty(gfxBmp)) { gfxBmp.ExcludeClip(region); gfxBmp.Clear(Color.Transparent); } gfxBmp.Dispose(); return bmp; } 

我正在改进PixelZerg的答案,其中不包括必要的使用和外部引用…

要使用下面的代码,只需创建一个ScreenCapture类实例,并将C#Winforms生成窗口的句柄传递给GetScreenshot例程。 这返回一个位图对象。 要将其写入JPG文件,请将位图对象传递给WriteBitmapToFile方法:

添加一个引用你的ScreenCapture类的using语句:

 using StackOverflow.Example.Utility; 

现在实例化ScreenCapture并使用它,如下所示:

 var sc = new ScreenCapture(); var bitmap = sc.GetScreenshot(parentContainer.Handle); sc.WriteBitmapToFile("temp.jpg", bitmap); 

以下是ScreenCapture类的完整,可编译的代码:

 using System; using System.Runtime.InteropServices; using System.Drawing; using System.Drawing.Imaging; namespace StackOverflow.Example.Utility { public class ScreenCapture { [DllImport("user32.dll")] static extern int GetWindowRgn(IntPtr hWnd, IntPtr hRgn); //Region Flags - The return value specifies the type of the region that the function obtains. It can be one of the following values. const int ERROR = 0; const int NULLREGION = 1; const int SIMPLEREGION = 2; const int COMPLEXREGION = 3; [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect); [DllImport("gdi32.dll")] static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags); [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left, Top, Right, Bottom; public RECT(int left, int top, int right, int bottom) { Left = left; Top = top; Right = right; Bottom = bottom; } public RECT(System.Drawing.Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { } public int X { get { return Left; } set { Right -= (Left - value); Left = value; } } public int Y { get { return Top; } set { Bottom -= (Top - value); Top = value; } } public int Height { get { return Bottom - Top; } set { Bottom = value + Top; } } public int Width { get { return Right - Left; } set { Right = value + Left; } } public System.Drawing.Point Location { get { return new System.Drawing.Point(Left, Top); } set { X = value.X; Y = value.Y; } } public System.Drawing.Size Size { get { return new System.Drawing.Size(Width, Height); } set { Width = value.Width; Height = value.Height; } } public static implicit operator System.Drawing.Rectangle(RECT r) { return new System.Drawing.Rectangle(r.Left, r.Top, r.Width, r.Height); } public static implicit operator RECT(System.Drawing.Rectangle r) { return new RECT(r); } public static bool operator ==(RECT r1, RECT r2) { return r1.Equals(r2); } public static bool operator !=(RECT r1, RECT r2) { return !r1.Equals(r2); } public bool Equals(RECT r) { return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom; } public override bool Equals(object obj) { if (obj is RECT) return Equals((RECT)obj); else if (obj is System.Drawing.Rectangle) return Equals(new RECT((System.Drawing.Rectangle)obj)); return false; } public override int GetHashCode() { return ((System.Drawing.Rectangle)this).GetHashCode(); } public override string ToString() { return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top, Right, Bottom); } } public Bitmap GetScreenshot(IntPtr ihandle) { IntPtr hwnd = ihandle;//handle here RECT rc; GetWindowRect(new HandleRef(null, hwnd), out rc); Bitmap bmp = new Bitmap(rc.Right - rc.Left, rc.Bottom - rc.Top, PixelFormat.Format32bppArgb); Graphics gfxBmp = Graphics.FromImage(bmp); IntPtr hdcBitmap; try { hdcBitmap = gfxBmp.GetHdc(); } catch { return null; } bool succeeded = PrintWindow(hwnd, hdcBitmap, 0); gfxBmp.ReleaseHdc(hdcBitmap); if (!succeeded) { gfxBmp.FillRectangle(new SolidBrush(Color.Gray), new Rectangle(Point.Empty, bmp.Size)); } IntPtr hRgn = CreateRectRgn(0, 0, 0, 0); GetWindowRgn(hwnd, hRgn); Region region = Region.FromHrgn(hRgn);//err here once if (!region.IsEmpty(gfxBmp)) { gfxBmp.ExcludeClip(region); gfxBmp.Clear(Color.Transparent); } gfxBmp.Dispose(); return bmp; } public void WriteBitmapToFile(string filename, Bitmap bitmap) { bitmap.Save(filename, ImageFormat.Jpeg); } } }