C# скриншот - проверка цвета в окне, а не во весь экран - PullRequest
0 голосов
/ 12 марта 2020

В настоящее время у меня есть код в c#, который получает цвет из указанного c местоположения (позиции курсора). Он работает хорошо, но работает так, что он берет «скриншот» на весь экран, а не только указывает c окно. Поэтому, если у меня есть какой-то другой windows выше того, который я наблюдаю, я получаю неправильный цветовой код. Есть ли простой способ изменить это, чтобы проверять только «скриншот» указанного окна c, а не полный экран? Вот

namespace MyApp
{
    using System;
    using System.Drawing;
    using System.Windows.Forms;

    internal class Screeny
    {
        private IntPtr window;

        public Bitmap CaptureFromScreen(Rectangle rect)
        {
            Bitmap image = !(rect == Rectangle.Empty) ? new Bitmap(rect.Width, rect.Height) : new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics graphics = Graphics.FromImage(image);
            if (rect == Rectangle.Empty)
            {
                graphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, image.Size, CopyPixelOperation.SourceCopy);
                return image;
            }
            graphics.CopyFromScreen(rect.X, rect.Y, 0, 0, rect.Size, CopyPixelOperation.SourceCopy);
            return image;
        }

        public bool ExpectColor(Point p, string rgb)
        {
            Color colorFromScreen = this.GetColorFromScreen(p);
            string[] strArray = rgb.Split(new char[] { '.' });
            return (((colorFromScreen.R.ToString() == strArray[0]) && (colorFromScreen.G.ToString() == strArray[1])) && (colorFromScreen.B.ToString() == strArray[2]));
        }

        public Color GetColorFromScreen(Point p)
        {
            Bitmap bitmap = this.CaptureFromScreen(new Rectangle(p, new Size(2, 2)));
            Color pixel = bitmap.GetPixel(0, 0);
            bitmap.Dispose();
            return pixel;
        }

        public void setWindow(IntPtr window)
        {
            this.window = window;
        }
    }
}

1 Ответ

1 голос
/ 12 марта 2020

Вам нужно получить окно Rect, которое вы пытаетесь захватить.
Чтобы выполнить sh эту задачу, вам нужна структура Rect и метод, который может получить Rect вашего окна:

[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
    public int left;
    public int top;
    public int right;
    public int bottom;
}

[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);

Далее просто используйте его:

public static Bitmap GetWindowScreenshotOfProcess(Process process)
{
    var rect = new Rect();
    GetWindowRect(process.MainWindowHandle, ref rect); // filling rect object

    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;

    if (width <= 0 || height <= 0)
    {
        return null;
    }

    // Just for example, window screenshot export:

    var bmp = new Bitmap(width, height);
    var graphics = Graphics.FromImage(bmp);
    graphics.CopyFromScreen(rect.left, rect.top, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy);
    graphics.DrawImage(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel);
    bmp.Save("c:\\temp\\window_screen.png");
    return bmp;
}

Это решение может получить скриншот только из окна переднего плана. Если у вас есть какой-либо другой windows перед целевым окном - вам нужно использовать внутренние функции WinAPI, как правильно упомянуто @ vasily.sib.

...