// ported form VB6 (Ctls\PortUtil\StdCtl.cpp:6176) private unsafe bool DICopy(IntPtr hdcDest, IntPtr hdcSrc, RECT rect, bool bStretch) { long i; // Get the bitmap from the DC by selecting in a 1x1 pixel temp bitmap IntPtr hNullBitmap = SafeNativeMethods.CreateBitmap(1, 1, 1, 1, IntPtr.Zero); if (hNullBitmap == IntPtr.Zero) { return(false); } try { IntPtr hBitmap = Gdi32.SelectObject(hdcSrc, hNullBitmap); if (hBitmap == IntPtr.Zero) { return(false); } // Restore original bitmap Gdi32.SelectObject(hdcSrc, hBitmap); if (!Gdi32.GetObjectW(hBitmap, out Gdi32.BITMAP bmp)) { return(false); } NativeMethods.BITMAPINFO_FLAT lpbmi = new NativeMethods.BITMAPINFO_FLAT { bmiHeader_biSize = Marshal.SizeOf <NativeMethods.BITMAPINFOHEADER>(), bmiHeader_biWidth = bmp.bmWidth, bmiHeader_biHeight = bmp.bmHeight, bmiHeader_biPlanes = 1, bmiHeader_biBitCount = (short)bmp.bmBitsPixel, bmiHeader_biCompression = NativeMethods.BI_RGB, bmiHeader_biSizeImage = 0, //Not needed since using BI_RGB bmiHeader_biXPelsPerMeter = 0, bmiHeader_biYPelsPerMeter = 0, bmiHeader_biClrUsed = 0, bmiHeader_biClrImportant = 0, bmiColors = new byte[NativeMethods.BITMAPINFO_MAX_COLORSIZE * 4] }; // Include the palette for 256 color bitmaps long iColors = 1 << (bmp.bmBitsPixel * bmp.bmPlanes); if (iColors <= 256) { byte[] aj = new byte[Marshal.SizeOf <NativeMethods.PALETTEENTRY>() * 256]; SafeNativeMethods.GetSystemPaletteEntries(hdcSrc, 0, (int)iColors, aj); fixed(byte *pcolors = lpbmi.bmiColors) { fixed(byte *ppal = aj) { NativeMethods.RGBQUAD * prgb = (NativeMethods.RGBQUAD *)pcolors; NativeMethods.PALETTEENTRY *lppe = (NativeMethods.PALETTEENTRY *)ppal; // Convert the palette entries to RGB quad entries for (i = 0; i < (int)iColors; i++) { prgb[i].rgbRed = lppe[i].peRed; prgb[i].rgbBlue = lppe[i].peBlue; prgb[i].rgbGreen = lppe[i].peGreen; } } } } // Allocate memory to hold the bitmap bits long bitsPerScanLine = bmp.bmBitsPixel * (long)bmp.bmWidth; long bytesPerScanLine = (bitsPerScanLine + 7) / 8; long totalBytesReqd = bytesPerScanLine * bmp.bmHeight; byte[] lpBits = new byte[totalBytesReqd]; // Get the bitmap bits int diRet = SafeNativeMethods.GetDIBits(hdcSrc, hBitmap, 0, bmp.bmHeight, lpBits, ref lpbmi, NativeMethods.DIB_RGB_COLORS); if (diRet == 0) { return(false); } // Set the destination coordiates depending on whether stretch-to-fit was chosen int xDest, yDest, cxDest, cyDest; if (bStretch) { xDest = rect.left; yDest = rect.top; cxDest = rect.right - rect.left; cyDest = rect.bottom - rect.top; } else { xDest = rect.left; yDest = rect.top; cxDest = bmp.bmWidth; cyDest = bmp.bmHeight; } // Paint the bitmap int iRet = SafeNativeMethods.StretchDIBits(hdcDest, xDest, yDest, cxDest, cyDest, 0, 0, bmp.bmWidth, bmp.bmHeight, lpBits, ref lpbmi, NativeMethods.DIB_RGB_COLORS, NativeMethods.SRCCOPY); if (iRet == NativeMethods.GDI_ERROR) { return(false); } } finally { Gdi32.DeleteObject(hNullBitmap); } return(true); }
// bFillBitmapInfo // // Fills in the fields of a BITMAPINFO so that we can create a bitmap // that matches the format of the display. // // This is done by creating a compatible bitmap and calling GetDIBits // to return the color masks. This is done with two calls. The first // call passes in biBitCount = 0 to GetDIBits which will fill in the // base BITMAPINFOHEADER data. The second call to GetDIBits (passing // in the BITMAPINFO filled in by the first call) will return the color // table or bitmasks, as appropriate. // // Returns: // TRUE if successful, FALSE otherwise. // // History: // 07-Jun-1995 -by- Gilman Wong [gilmanw] // Wrote it. // // 15-Nov-2000 -by- Chris Anderson [chrisan] // Ported it to C# // private bool bFillBitmapInfo(IntPtr hdc, IntPtr hpal, ref NativeMethods.BITMAPINFO_FLAT pbmi) { IntPtr hbm = IntPtr.Zero; bool bRet = false; try { // // Create a dummy bitmap from which we can query color format info // about the device surface. // hbm = SafeNativeMethods.CreateCompatibleBitmap(new HandleRef(null, hdc), 1, 1); if (hbm == IntPtr.Zero) { throw new OutOfMemoryException(SR.GetString(SR.GraphicsBufferQueryFail)); } pbmi.bmiHeader_biSize = Marshal.SizeOf(typeof(NativeMethods.BITMAPINFOHEADER)); pbmi.bmiColors = new byte[NativeMethods.BITMAPINFO_MAX_COLORSIZE * 4]; // // Call first time to fill in BITMAPINFO header. // IntPtr diRet = SafeNativeMethods.GetDIBits(new HandleRef(null, hdc), new HandleRef(null, hbm), 0, 0, IntPtr.Zero, ref pbmi, NativeMethods.DIB_RGB_COLORS); if (pbmi.bmiHeader_biBitCount <= 8) { bRet = bFillColorTable(hdc, hpal, ref pbmi); } else { if (pbmi.bmiHeader_biCompression == NativeMethods.BI_BITFIELDS) { // // Call a second time to get the color masks. // It's a GetDIBits Win32 "feature". // SafeNativeMethods.GetDIBits(new HandleRef(null, hdc), new HandleRef(null, hbm), 0, pbmi.bmiHeader_biHeight, IntPtr.Zero, ref pbmi, NativeMethods.DIB_RGB_COLORS); } bRet = true; } } finally { if (hbm != IntPtr.Zero) { SafeNativeMethods.DeleteObject(new HandleRef(null, hbm)); hbm = IntPtr.Zero; } } return(bRet); }