-1

I do have a working method however it is fairly resource intensive and I am looking for a better way. Running the code below was suggested on a response to a similar question here.

However running said code yields a System.OutOfMemoryException.

The exception happens @ using (Graphics gdest = Graphics.FromImage(screenPixel)) {

Current code:

Bitmap screenPixel = new Bitmap(1, 1, PixelFormat.Format16bppArgb1555);
using (Graphics gdest = Graphics.FromImage(screenPixel)) {
    using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero)) {
        IntPtr hSrcDC = gsrc.GetHdc();
        IntPtr hDC = gdest.GetHdc();
        int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, x, y, (int)CopyPixelOperation.SourceCopy);
        gdest.ReleaseHdc();
        gsrc.ReleaseHdc();
        }
   }
    return screenPixel.GetPixel(0, 0);

EDIT:

Okay so I've fixed the issue I was having above with the following code. However now I am only getting the color black (0,0,0) returned.

this.screenPixel = new Bitmap(1, 1, PixelFormat.Format16bppRgb555);
using (Graphics gdest = Graphics.FromImage(this.screenPixel)) {
    using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero)) {
        IntPtr hSrcDC = gsrc.GetHdc();
        IntPtr hDC = gdest.GetHdc();
        int retval = BitBlt(hDC, 0, 0, width, height, hSrcDC, x, y, (int)CopyPixelOperation.SourceCopy);
        gdest.ReleaseHdc();
        gsrc.ReleaseHdc();
        }
}
Color result = screenPixel.GetPixel(0, 0);
Console.WriteLine(result.R + " " + result.G + " " + result.B);
GC.SuppressFinalize(this.screenPixel);
this.screenPixel.Dispose();
return result;
walshie4
  • 1,396
  • 2
  • 11
  • 16

1 Answers1

1

This seems to work here:

using System.Runtime.InteropServices;
//... 


[DllImport("gdi32.dll")]
public static extern int BitBlt(IntPtr hObject, int nXDest, int nYDest, 
   int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, int  dwRop);

//..

    Bitmap screenPixel = new Bitmap(1, 1, PixelFormat.Format32bppRgb);
    using (Graphics gdest = Graphics.FromImage(screenPixel))
    {
        using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero))
        {
            IntPtr hSrcDC = gsrc.GetHdc();
            IntPtr hDC = gdest.GetHdc();
            int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, x, y,
                                    (int) CopyPixelOperation.SourceCopy);
            gdest.ReleaseHdc();
            gsrc.ReleaseHdc();
        }
    }
    Color c =  screenPixel.GetPixel(0, 0);
    return c;

Note 1:

  • I have changed the pixel format to match my screen.
  • I have fiddled with the BitBlt declaration

Note 2:

According to this post you might as well use Graphics.CopyFromScreen directly as it will use BitBlt anyway. This would be safer and less trouble imo.

Community
  • 1
  • 1
TaW
  • 53,122
  • 8
  • 69
  • 111
  • Can you tell me where the `(int)0x00CC0020` value comes from? – walshie4 Aug 12 '14 at 18:45
  • [Here on pinvoke](http://www.pinvoke.net/default.aspx/gdi32.bitblt) is a description of bitBlt and the `enum TernaryRasterOperations`. Since I thought it was missing I copied the value for `SRCCOPY`. Silly me! Note that you may want to use `int bpp = Screen.PrimaryScreen.BitsPerPixel;` to determine the color depth of your screen. – TaW Aug 12 '14 at 18:49