mcnamaragio

Can you please tell me why I'm getting generic error in gdi+ error in this code:

Code Snippet

IntPtr hdcSrc = winapi.GetWindowDC(winapi.GetDesktopWindow());
// get the size
winapi.RECT windowRect = new winapi.RECT();
winapi.GetWindowRect(winapi.GetDesktopWindow(), ref windowRect);
int width = windowRect.right - windowRect.left;
int height = windowRect.bottom - windowRect.top;
// create a device context we can copy to
IntPtr hdcDest = winapi.CreateCompatibleDC(hdcSrc);
// create a bitmap we can copy it to,
// using GetDeviceCaps to get the width/height
IntPtr hBitmap = winapi.CreateCompatibleBitmap(hdcSrc, width, height);
// select the bitmap object
IntPtr hOld = winapi.SelectObject(hdcDest, hBitmap);
// bitblt over
winapi.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, winapi.SRCCOPY);
// restore selection
winapi.SelectObject(hdcDest, hOld);
// clean up
winapi.DeleteDC(hdcDest);
winapi.ReleaseDC(winapi.GetDesktopWindow(), hdcSrc);

// get a .NET image object for it
Image img = Image.FromHbitmap(hBitmap);
// free up the Bitmap object
winapi.DeleteObject(hBitmap);

img.Save(filename, format);
img.Dispose();


The error occurs when I call img.Save(filename, format);

the function takes screenshot of desktop. I call this function many times from my application. First it works and then the exception is thrown. Why Can you help me Thanks


Re: Visual C# General generic error in gdi+

Mark Dawson

Hi,

is the error thrown the second time you try to save or is it at different intervals

Mark.






Re: Visual C# General generic error in gdi+

mcnamaragio

It is about third or fourth. Every time this function is called the filename doesn't exist so that shouldn't be a problem




Re: Visual C# General generic error in gdi+

Mark Dawson

I am not sure, normally when you see a generic GDI+ exception it means the data is corrupt or there is some underlying stream that has been close too early.

I have some other code I use to capture the desktop, I have not seen this issue, you are more than welcome to try it out if you cannot figure out this issue: http://themightycoder.spaces.live.com/blog/cns!EBFBA22CD769E10B!133.entry

Mark.






Re: Visual C# General generic error in gdi+

mcnamaragio

Thanks I'll try that but as you see the issue is in saving to file not taking screenshot Smile




Re: Visual C# General generic error in gdi+

Mark Dawson

Does the issue still happen if you move the following line until after saving the image:

// free up the Bitmap object
winapi.DeleteObject(hBitmap);

I am guessing when you call Image.FromHBitmap the .Net framework creates a copy of the original bitmap, but the documentation does not say explicitly, it just says "Creates a Bitmap object from a handle to a GDI bitmap." so it does not completely exclude the possibility these two items are still linked in some way.

Mark.






Re: Visual C# General generic error in gdi+

mcnamaragio

I thought about that but in that case it would throw exception on the first time to. I've tried commenting that line




Re: Visual C# General generic error in gdi+

Figo Fei - MSFT

Hi, mcnamaragio

You could get others' implementation for your help: http://www.c-sharpcorner.com/UploadFile/perrylee/ScreenCapture11142005234547PM/ScreenCapture.aspx

http://www.developerfusion.co.uk/show/4630/

Thanks




Re: Visual C# General generic error in gdi+

mcnamaragio

The source code on the second link is the same that I've posted




Re: Visual C# General generic error in gdi+

Figo Fei - MSFT

Hi, mcnamaragio

Try the following code, (I've tested without problem):

Code Snippet

class GDI32
{
[DllImport("GDI32.dll")]
public static extern bool BitBlt(int hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, int hdcSrc, int nXSrc, int nYSrc, int dwRop);
[DllImport("GDI32.dll")]
public static extern int CreateCompatibleBitmap(int hdc, int nWidth, int nHeight);
[DllImport("GDI32.dll")]
public static extern int CreateCompatibleDC(int hdc);
[DllImport("GDI32.dll")]
public static extern bool DeleteDC(int hdc);
[DllImport("GDI32.dll")]
public static extern bool DeleteObject(int hObject);
[DllImport("GDI32.dll")]
public static extern int GetDeviceCaps(int hdc, int nIndex);
[DllImport("GDI32.dll")]
public static extern int SelectObject(int hdc, int hgdiobj);
class User32
{
[DllImport("User32.dll")]
public static extern int GetDesktopWindow();
[DllImport("User32.dll")]
public static extern int GetWindowDC(int hWnd);
[DllImport("User32.dll")]
public static extern int ReleaseDC(int hWnd, int hDC);
}
public class Example
{
public void CaptureScreen(string fileName, ImageFormat imageFormat)
{
int hdcSrc = User32.GetWindowDC(User32.GetDesktopWindow()), // Get a handle to the desktop window
hdcDest = GDI32.CreateCompatibleDC(hdcSrc), // Create a memory device context
hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, // Create a bitmap and place it in the memory DC
GDI32.GetDeviceCaps(hdcSrc, 8), GDI32.GetDeviceCaps(hdcSrc, 10));
// GDI32.GetDeviceCaps(hdcSrc,8) returns the width of the desktop window
// GDI32.GetDeviceCaps(hdcSrc,10) returns the height of the desktop window
GDI32.SelectObject(hdcDest, hBitmap); // Required to create a color bitmap
GDI32.BitBlt(hdcDest, 0, 0, GDI32.GetDeviceCaps(hdcSrc, 8), // Copy the on-screen image into the memory DC
GDI32.GetDeviceCaps(hdcSrc, 10), hdcSrc, 0, 0, 0x00CC0020);
SaveImageAs(hBitmap, fileName, imageFormat); // Save the screen-capture to the specified file using the designated image format
Cleanup(hBitmap, hdcSrc, hdcDest); // Free system resources
}
private void Cleanup(int hBitmap, int hdcSrc, int hdcDest)
{
// Release the device context resources back to the system
User32.ReleaseDC(User32.GetDesktopWindow(), hdcSrc);
GDI32.DeleteDC(hdcDest);
GDI32.DeleteObject(hBitmap);
}
private void SaveImageAs(int hBitmap, string fileName, ImageFormat imageFormat)
{
// Create a bitmap from the Windows handle
Bitmap image = new Bitmap(Image.FromHbitmap(new IntPtr(hBitmap)),
Image.FromHbitmap(new IntPtr(hBitmap)).Width,
Image.FromHbitmap(new IntPtr(hBitmap)).Height);
image.Save(fileName, imageFormat);
}
}
}

private void button1_Click(object sender, EventArgs e)
{
GDI32.Example ex = new GDI32.Example();
ex.CaptureScreen(@"D:\t.bmp", ImageFormat.Bmp);
MessageBox.Show("success");
}

Thanks