1

I need to retrieve screenshots of all the windows associated with a program. Right now I am just trying to get this to work for the main window.

Right after image = Image.FromHbitmap(mem); the error I get is "A generic error occurred in GDI+." I was trying to follow this tutorial

http://www.dreamincode.net/forums/topic/34831-taking-a-screen-shot-in-c%23/

I think I am messing up with my pointers, specifically at these three lines:

        IntPtr oldBmp = (IntPtr)Win32Stuff.SelectObject(mem, windowImage);
        Win32Stuff.BitBlt(mem, 0, 0, windowwidth, windowheight, windowDC, 0, 0, 13369376);
        Win32Stuff.SelectObject(mem, oldBmp);

If I understand correctly, oldBmp and mem point to windowImage, then mem points to the output from BitBlt, then I don't get this line where now mem points back to oldBmp. I tried commenting it out to see if this what was messing it up, but I get the same generic error.

Here is the code in its entirety:

public static class Win32Stuff
{
    [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
    public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
    [DllImport("user32.dll", EntryPoint = "GetWindowDC")]
    public static extern IntPtr GetWindowDC(IntPtr hWnd);

    [DllImport("gdi32", EntryPoint = "CreateCompatibleDC")]
    public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
    [DllImport("gdi32", EntryPoint = "CreateCompatibleBitmap")]
    public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
    [DllImport("gdi32", EntryPoint = "SelectObject")]
    public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
    [DllImport("gdi32", EntryPoint = "BitBlt")]
    public static extern bool BitBlt(IntPtr hDestDC, int X, int Y, int nWidth, int nHeight, IntPtr hSrcDC, int SrcX, int SrcY, int Rop);
    [DllImport("gdi32", EntryPoint = "DeleteDC")]
    public static extern IntPtr DeleteDC(IntPtr hDC);
}

    public static void getScreenShot()
    {
        int windowwidth;
        int windowheight;
        Bitmap image;

        IntPtr windowHandle = Process.GetProcessesByName("firefox")[0].MainWindowHandle;
        IntPtr windowDC = Win32Stuff.GetWindowDC(windowHandle);
        IntPtr mem = Win32Stuff.CreateCompatibleDC(windowDC);

        //need to change this
        windowheight = 1920;
        windowwidth = 1920;

        IntPtr windowImage = Win32Stuff.CreateCompatibleBitmap(windowDC, windowwidth, windowheight);
        IntPtr oldBmp = (IntPtr)Win32Stuff.SelectObject(mem, windowImage);
        Win32Stuff.BitBlt(mem, 0, 0, windowwidth, windowheight, windowDC, 0, 0, 13369376);
        //Win32Stuff.SelectObject(mem, oldBmp);
        image = Image.FromHbitmap(mem);

        Win32Stuff.DeleteDC(mem);
        Win32Stuff.ReleaseDC(windowHandle, mem);
    }

How can I see what the specific error is, and why won't Image.FromHbitmap() output a GDI bitmap from my pointer?

Adam
  • 1,483
  • 4
  • 21
  • 50
  • Call the API GetLastError() to see what is the error – Matt May 02 '14 at 15:26
  • so I called GetLastError() like so ` try { image = Image.FromHbitmap(mem); } catch (Exception) { uint error = Win32Stuff.GetLastError(); }` and the error i get is 5 which I think is insufficient buffer. – Adam May 02 '14 at 16:09
  • 5 is access denied. Are you writing a GUI application? or a back end service? – Matt May 02 '14 at 16:19
  • It is going into the client side of a GUI application. I got that error though running this code in a standalone console app i made for testing. I haven't tested it yet in the program – Adam May 02 '14 at 16:59
  • This article shows how to get the whole screen, or any window. http://www.developerfusion.com/code/4630/capture-a-screen-shot/. See http://stackoverflow.com/a/1163781/56778 for a usage example. – Jim Mischel May 02 '14 at 18:11

1 Answers1

0

Change

image = Image.FromHbitmap(mem);

to

image = Image.FromHbitmap(windowImage);