Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search for Pixel on screen

I want to find a specific pixel coordinates from screen. Here's my code (I'm mega-super-newbie, I just started today with C#:

static string GetPixel(int X, int Y)
{
    Point position = new Point(X, Y);
    var bitmap = new Bitmap(1, 1);
    var graphics = Graphics.FromImage(bitmap);

    graphics.CopyFromScreen(position, new Point(0, 0), new Size(1, 1));

    var _Pixel = bitmap.GetPixel(0, 0);
    return "0x" + _Pixel.ToArgb().ToString("x").ToUpper().Remove(0, 2);
    //it returns a pixel color in a form of "0xFFFFFF" hex code
    //I had NO idea how to convert it to hex code so I did that :P
}

static void Main()
{
    // for x = 1 to screen width...
    for (int x = 1; x <= Screen.PrimaryScreen.Bounds.Bottom; x++)
    {
        // for x = 1 and y = 1 to screen height...
        for (int y = 1; y <= Screen.PrimaryScreen.Bounds.Height; y++)
        {
            string pixel = GetPixel(x, y);
            if (pixel == "0x007ACC") //blue color
            {
                MessageBox.Show("Found 0x007ACC at: (" + x + "," + y + ")");
                break; //exit loop
            }
        }
    }
}

edit: Here's an error which appears when I run this script:

An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll

Additional information: Index and length must refer to a location within the string

I have experience in AutoIt, it's my first day with C# ^^ Regards

like image 552
VixinG Avatar asked Nov 03 '22 10:11

VixinG


1 Answers

Welcome to SO.

Most coordinates and other things are 0-based, just as in arrays.

That being said, it would be best to use the Bounds' X/Y/Width and Height properties for the loops:

var bounds = Screen.PrimaryScreen.Bounds;
for (int x = bounds.X; x < bounds.Width; x++) {
  for(int y = bounds.Y; y < bounds.Height; y++) {
    ..

And the proper way to convert the ARGB value to hex is to use the string.Format() method:

string hex = string.Format("0x{0:8x}", argb);

EDIT: Apparently Graphics.CopyFromScreen leaks handles like there's no tomorrow, which causes strange exceptions to be thrown when no more handles are available (source)

A quick workaround for your scenario could be to capture the whole screen once and then search in the bitmap, i.e. Graphics.CopyFromScreen(new Position(0, 0), new Position(0, 0), new Size(bounds.Width, bounds.Height));

Unfortunately this didn't get fixed in .Net 4.0 (don't know about 4.5), so the only proper solution seems to be to P/Invoke the native GDI functions, as described here.

like image 155
M.Stramm Avatar answered Nov 09 '22 15:11

M.Stramm