Захват экрана окна ручкой

Я пытаюсь захватить только определенное окно на рабочем столе, но получаю смешанное изображение, часть окна и часть рабочего стола.

Что мне не хватает?

Вот мой код:

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);
 Hans Passant20 июн. 2016 г., 23:21
Хрустальный шар говорит, что ты забылобъявите ваше приложение dpiAware.

Ответы на вопрос(2)

Решение Вопроса

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;
 }
 Jack21 июн. 2016 г., 00:54
Я скоро проголосую за твой ответ, как только мне снова удастся ... слишком много проголосовал сегодня, ха-ха
 Jack21 июн. 2016 г., 00:51
Спасибо, это гораздо лучший метод
 Paul B.09 нояб. 2018 г., 14:59
Отличный код! Вы должны добавитьWin32.DeleteObject(hRgn), хоть. Такжеbmp а такжеgfxBmp должны быть утилизированы при возвращенииnull.

Я улучшаю ответ PixelZerg, который не включает необходимые ссылки и внешние ссылки ...

Чтобы использовать приведенный ниже код, просто создайте экземпляр класса ScreenCapture и передайте дескриптор сгенерированного окна C # Winforms подпрограмме GetScreenshot. Это возвращает растровый объект. Чтобы записать это в файл JPG, передайте объект растрового изображения в метод WriteBitmapToFile:

Добавьте оператор using, который ссылается на ваш класс ScreenCapture:

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);
        }
    }
}

Ваш ответ на вопрос