Capture screen of Window by handle

前端 未结 2 451
借酒劲吻你
借酒劲吻你 2020-12-17 05:53

I\'m trying to capture only a specific Window in the desktop but I\'m getting a mixed image, part of window and part desktop area.

What am I missing?

Here\'s

相关标签:
2条回答
  • 2020-12-17 06:41

    I'm improving on PixelZerg's answer, which doesn't include necessary using and external references...

    To use the code below, simply create a ScreenCapture class instance and pass the handle of your C# Winforms-generated window to the GetScreenshot routine. This returns a bitmap object. To write that to a JPG file, pass the bitmap object to the WriteBitmapToFile method:

    Add a using statement that references your ScreenCapture class:

    using StackOverflow.Example.Utility;
    

    Now instantiate ScreenCapture and use it as shown:

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

    Here is the complete, compilable code for the ScreenCapture class:

    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);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-17 07:00

    I think the problem in your code is this line:

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

    It should be:

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

    Here is the method I personally use to get an image of a particular window - it might come in handy:

    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;
     }
    
    0 讨论(0)
提交回复
热议问题