When capturing a window manually with the Print Screen
+Alt
key combo, I get the following:
but if I try to do it programmatically using Windows API, I get this:
Why the discrepancy? How do I get the first programmatically?
Here is my code:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);
public Bitmap PrintWindow()
{
Bitmap bmp = new Bitmap(windowRect.Width, windowRect.Height, PixelFormat.Format32bppArgb);
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
bool success = PrintWindow(windowHandle, hdcBitmap, 0);
gfxBmp.ReleaseHdc(hdcBitmap);
if (!success)
{
Console.WriteLine("Error copying image");
Console.WriteLine(getLastError());
}
gfxBmp.Dispose();
return bmp;
}
Update: Doing it with BitBlt does the same thing.
Here's code from CodeProject that still returns a black-masked image:
public Image CaptureWindow(IntPtr handle)
{
// get te hDC of the target window
IntPtr hdcSrc = User32.GetWindowDC(handle);
// get the size
User32.RECT windowRect = new User32.RECT();
User32.GetWindowRect(handle,ref windowRect);
int width = windowRect.right - windowRect.left;
int height = windowRect.bottom - windowRect.top;
// create a device context we can copy to
IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
// create a bitmap we can copy it to,
// using GetDeviceCaps to get the width/height
IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc,width,height);
// select the bitmap object
IntPtr hOld = GDI32.SelectObject(hdcDest,hBitmap);
// bitblt over
GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
// restore selection
GDI32.SelectObject(hdcDest,hOld);
// clean up
GDI32.DeleteDC(hdcDest);
User32.ReleaseDC(handle,hdcSrc);
// get a .NET image object for it
Image img = Image.FromHbitmap(hBitmap);
// free up the Bitmap object
GDI32.DeleteObject(hBitmap);
img.Save("SampleImage.png");
return img;
}
I have tried many combinations of CopyPixelOperation
, (somewhere around 15,000 of the 131,000) but it still doesn't work.
Using Windows 8, AMD Radeon HD 6870.
Update 2
It seems that the window is transparent, allowing the blue color of the window to bleed through. When I change the window color to black (using the Windows personalization dialog), I get roughly something similar to the second window. The border is still missing though.
I haven't found a solution, but it's insight into the problem.
PrintWindow()
, how did you manufacture the DC you sent to the API call? – ConnivePixelFormat.Format24bppRgb
? – Ruhr