You are here: Home » Builder » [ En ] » Printing a TBitmap with StretchDIBits

Printing a TBitmap with StretchDIBits

2 February |

  The simple way to print a TBitmap is to use the Draw method of a TPrinter Canvas ThePrinterCanvas->Draw ( PositionX, PositionY, TheBitmap);. This works, except that on many machines this will fail to print (or print out too small). The following code will print the TBitmap at a size that is adjusted for the printer device using StretchDIBits. You could change the scaling and have it print to whatever size you want…

The image must contain a Bitmap. This particular function will only work if it is a Bitmap, icons and cursors will not work.

[cpp]
/********************************************************************************************
* NAME:
* PrintImage
* PURPOSE:
* Print a bitmap with StretchDIBits
* NOTES:
* The image must contain a Bitmap. This particular function will only
* work if it is a Bitmap, icons and cursors will not work.
*
* PARAMS: PrinterCanvas : printer canvas (TPrinter->Canvas)
* pX : bitmap X position on printer page
* pY : bitmap Y position on printer page
* TheBitmap: TBitmap to be printed
* RETURNS:
* void
**********************************************************************************************/
void __fastcall TForm1::PrintImage(TCanvas *PrinterCanvas,int pX,int pY, Graphics::TBitmap *TheBitmap)
{

// create a memory dc for the image
HDC h_dc = TheBitmap->Canvas->Handle;
int bmp_w = TheBitmap->Width, bmp_h = TheBitmap->Height;

HDC h_mem_dc = ::CreateCompatibleDC (h_dc);
HBITMAP h_mem_bmp = ::CreateCompatibleBitmap (h_dc, bmp_w, bmp_h);
HBITMAP h_old_bmp = ::SelectObject (h_mem_dc, h_mem_bmp);

// fix up bad video drivers
bool is_pal_dev = false;
LOGPALETTE *pal;
HPALETTE h_pal, h_old_pal;

if ( ::GetDeviceCaps (TheBitmap->Canvas->Handle, RASTERCAPS) & RC_PALETTE)
{
pal = static_cast(malloc (sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256)));
memset (pal, 0, sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256));
pal->palVersion = 0×300;
pal->palNumEntries = ::GetSystemPaletteEntries(TheBitmap->Canvas->Handle, 0, 256, pal->palPalEntry);
if (pal->palNumEntries != 0)
{
h_pal = ::CreatePalette (pal);
h_old_pal = ::SelectPalette (h_mem_dc, h_pal, false);
is_pal_dev = true;
}
else
{
free (pal);
}
}

// copy the image on to the memory dc
::BitBlt (h_mem_dc, 0, 0, bmp_w, bmp_h, h_dc, 0, 0, SRCCOPY);

if (is_pal_dev)
{
::SelectPalette (h_mem_dc, h_old_pal, false);
::DeleteObject (h_pal);
}

// delete the mem dc
::SelectObject (h_mem_dc, h_old_bmp);
::DeleteDC (h_mem_dc);

// get memory for a BITMAPIFO Structure
HANDLE h_bmp_info = ::GlobalAlloc (GHND, sizeof (BITMAPINFO) + (sizeof (RGBQUAD) * 256));
BITMAPINFO* bmp_info = static_cast(::GlobalLock (h_bmp_info));
//Set up the structure

memset (bmp_info, NULL, sizeof (BITMAPINFO) + (sizeof (RGBQUAD) * 255));
bmp_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmp_info->bmiHeader.biPlanes = 1;
bmp_info->bmiHeader.biBitCount = 16;//or 8
bmp_info->bmiHeader.biWidth = bmp_w;
bmp_info->bmiHeader.biHeight = bmp_h;
bmp_info->bmiHeader.biCompression = BI_RGB;

// find out how much memory for the bits
::GetDIBits (h_dc, h_mem_bmp, 0, bmp_h, NULL, bmp_info, DIB_RGB_COLORS);

// Allocate memory for the bits
HANDLE h_bits = GlobalAlloc (GHND, bmp_info->bmiHeader.biSizeImage);
void *bits = ::GlobalLock (h_bits);

// this time get the bits
::GetDIBits (h_dc, h_mem_bmp, 0, bmp_h, bits, bmp_info, DIB_RGB_COLORS);

// fix up for bad video driver
if (is_pal_dev)
{
for (int i = 0; i < pal->palNumEntries; i++)
{
bmp_info->bmiColors[i].rgbRed = pal->palPalEntry[i].peRed;
bmp_info->bmiColors[i].rgbGreen = pal->palPalEntry[i].peGreen;
bmp_info->bmiColors[i].rgbBlue = pal->palPalEntry[i].peBlue;
}
free (pal);
}

// fix up for print with palette
is_pal_dev = false;
if ( ::GetDeviceCaps (h_dc, RASTERCAPS) & RC_PALETTE)
{
pal = static_cast(malloc (sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256)));
memset (pal, 0, sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256));
pal->palVersion = 0×300;
pal->palNumEntries = 256;
for (int i = 0; pal->palNumEntries; i++)
{
pal->palPalEntry[i].peRed = bmp_info->bmiColors[i].rgbRed;
pal->palPalEntry[i].peGreen = bmp_info->bmiColors[i].rgbGreen;
pal->palPalEntry[i].peBlue = bmp_info->bmiColors[i].rgbBlue;
}
h_pal = CreatePalette(pal);
free (pal);
h_old_pal = SelectPalette(PrinterCanvas->Handle, h_pal, false);
is_pal_dev = true;
}

// adjust bitmap dimensions for the printer device:
int PrnXRes= GetDeviceCaps(PrinterCanvas->Handle, LOGPIXELSX); //Get dpi of printer along width
int PrnYRes= GetDeviceCaps(PrinterCanvas->Handle, LOGPIXELSY); //Get dpi of printer along height
bmp_w= floor(((double)TheBitmap->Width / (double)Screen->PixelsPerInch) * (double)PrnXRes);
bmp_h= floor(((double)TheBitmap->Height / (double)Screen->PixelsPerInch) * (double)PrnYRes);

// send the bits to the printer
StretchDIBits(PrinterCanvas->Handle, pX,pY, bmp_w, bmp_h,
0, 0, TheBitmap->Width,TheBitmap->Height, bits,bmp_info, DIB_RGB_COLORS, SRCCOPY);

// clean up
::DeleteObject (h_mem_bmp);
if (is_pal_dev)
{
::SelectObject (PrinterCanvas->Handle, h_old_pal);
::DeleteObject (h_pal);
}
::GlobalUnlock (bits);
::GlobalFree (h_bits);
::GlobalUnlock (bmp_info);
::GlobalFree (h_bmp_info);
}
[/cpp]

You like this post? Be the first of my friends to give me a beer! click here. Thanks!
Filed under

Builder, [ En ]

| Tags:

Comments are closed.