关于VC 打印位图的问题
VC 打印位图
    关于位图的打印,很多人对此很困惑,在这方面产生的问题也很多,主要包括以下几点。 
    1:打印的图片太小;
    2:根本打印不出来位图
    3:打印预览可见、但打印不出来;
    产生这些问题的根本原因,在于对位图的理解不够深刻。
    一个CBitmap对象,可能是DDB位图(设备相关位图),或者DIB位图(设备无关位图),其中,一个设备兼容的内存DC中,只能选择该设备兼容的DDB位图或者单色的位图。注意,位图只能被选择进入到设备兼容的内存DC中,并不能选择进入到真实的dc中,这就是有时候根本打印不出图片的原因。
    至于打印图片太小的问题,主要是因为衡量位图大小的单位是横向和纵向的像素数,而不是确切的长度,所以如果把一个图片映射到屏幕上,会出现一个比较大的图像,但是打印机的分辨率比屏幕高很多(屏幕一般是96dpi,而打印机最少一般也有300dpi),如果把位图不缩放地映射到打印机上,则必然要小很多。解决该类问题的方法是使用StretchBlt拉伸显示图像。
    另外LoadImage函数中使用LR_CREATEDIBSECTION选项产生的DIB位图可以被选择进入任何设备兼容的内存DC中。因此可以使用LoadImage函数加载一个位图文件或者资源,直接把位图通过StretchBlt打印出来。下面是把一个位图文件进行打印的相关代码:
 
void DrawBMP(CDC* pDC,int iLogPixelX,int iLogPixelY,const char *strFileName)
{
         CDC          MemDC; // 内存设备环境指针,在视的整个存在过程都将存在
         CBitmap         Bitmap,*pOldBmp;      
         CRect                Source, Dest; // 记录源位图尺寸和最终显示尺寸
         BITMAP         bm;
         if(MemDC.GetSafeHdc() == NULL)
         {
                  HBITMAP hbitmap=(HBITMAP)LoadImage(0,strFileName,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);
                  Bitmap.Attach(hbitmap);
                  MemDC.CreateCompatibleDC(pDC);
                  Bitmap.GetObject(sizeof(bm),&bm);
                  pOldBmp=MemDC.SelectObject(&Bitmap);
                  Source.top=0;
                  Source.left=0;
                  Source.right= bm.bmWidth;
                  Source.bottom = bm.bmHeight;
                   Dest = Source;
         }
         pDC->DPtoLP(&Dest);
         if(pDC->IsPrinting())
         {
                  Dest.left=(int)(Dest.left*((double)pDC->GetDeviceCaps(LOGPIXELSX))/iLogPixelX);
                  Dest.right=(int)(Dest.right*((double)pDC->GetDeviceCaps(LOGPIXELSX))/iLogPixelX);
                  Dest.top=(int)(Dest.top*((double)pDC->GetDeviceCaps(LOGPIXELSY))/iLogPixelY);
                  Dest.bottom=(int)(Dest.bottom*((double)pDC->GetDeviceCaps(LOGPIXELSY))/iLogPixelY);
         }
         pDC->StretchBlt(Dest.left, Dest.top, Dest.right, Dest.bottom,
                  &MemDC, Source.left, Source.top, Source.right,Source.bottom, SRCCOPY);
         MemDC.SelectObject(pOldBmp);
         Bitmap.DeleteObject();
         MemDC.DeleteDC();
         return;
}
    但是对于显示设备兼容的DDB位图的打印则不是那么简单,比如屏幕截图,这种位图不能选择进入打印设备兼容的内存DC中,对于这种问题的处理,一般是通过转化成DIB位图,然后使用StretchDIBits函数把位图显示在DC上,下面是一个可以打印任何位图的函数代码:
 
void Draw(HDC hDC,HBITMAP hBmp,int iX,int iY,double dScaleX=1.0,double dScaleY=1.0,int iWidth=0,int iLength=0)
{
         HPALETTE hPal;
         BITMAP                     bm;
         BITMAPINFOHEADER         bi;
         LPBITMAPINFOHEADER          lpbi;
         DWORD                      dwLen;
         HANDLE                     hDIB;
         HANDLE                     handle;
         HDC                            hDC1;
         if(GetDeviceCaps(hDC,RASTERCAPS) & RC_PALETTE )
         {
                   UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256);
                  LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
                  pLP->palVersion = 0x300;
                  pLP->palNumEntries =GetSystemPaletteEntries( hDC, 0, 255, pLP->palPalEntry );
                  hPal=CreatePalette(pLP );
                   delete[] pLP;
         }
         if (hPal==NULL)         hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
         ::GetObject(hBmp,sizeof(bm),(LPSTR)&bm);
         bi.biSize             = sizeof(BITMAPINFOHEADER);
         bi.biWidth                   = bm.bmWidth;
         bi.biHeight                    = bm.bmHeight;
         bi.biPlanes                    = 1;
         bi.biBitCount                 = bm.bmPlanes * bm.bmBitsPixel;
         bi.biCompression         = BI_RGB;
         bi.biSizeImage              = 0;
         bi.biXPelsPerMeter       = 0;
         bi.biYPelsPerMeter       = 0;
         bi.biClrUsed                   = 0;
         bi.biClrImportant = 0;
         int nColors = (1 << bi.biBitCount);
         if( nColors > 256 )
                  nColors = 0;
         dwLen  = bi.biSize + nColors * sizeof(RGBQUAD);
         hDC1 = ::GetDC(NULL);
         hPal = SelectPalette(hDC1,hPal,FALSE);
         RealizePalette(hDC1);
         hDIB = GlobalAlloc(GMEM_FIXED,dwLen);
         if (!hDIB)
         {
                  SelectPalette(hDC1,hPal,FALSE);
        ::ReleaseDC(NULL,hDC1);
                  DeleteObject(hPal);
                   return ;
         }
         lpbi = (LPBITMAPINFOHEADER)hDIB;
         *lpbi = bi;
         ::GetDIBits(hDC1, hBmp, 0L, (DWORD)bi.biHeight,
                  (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);
         bi = *lpbi;
         if (bi.biSizeImage == 0)
                  bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)* bi.biHeight;
         dwLen += bi.biSizeImage;
         if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))
                   hDIB = handle;
         else
         {
                  GlobalFree(hDIB);
                  SelectPalette(hDC1,hPal,FALSE);
                  ::ReleaseDC(NULL,hDC1);
                  DeleteObject(hPal);
                   return ;
         }
         lpbi = (LPBITMAPINFOHEADER)hDIB;
         BOOL bGotBits = GetDIBits( hDC1, hBmp,0L,(DWORD)bi.biHeight,(LPBYTE)lpbi+ (bi.biSize + nColors * sizeof(RGBQUAD)),
                  (LPBITMAPINFO)lpbi,(DWORD)DIB_RGB_COLORS);
         if( !bGotBits )
         {
                  GlobalFree(hDIB);
                  SelectPalette(hDC1,hPal,FALSE);
                  ::ReleaseDC(NULL,hDC1);
                  DeleteObject(hPal);
                   return;
         }
         if(iWidth==0||iLength==0)
{
                  iWidth=lpbi->biWidth;
                  iLength=lpbi->biHeight;
                  iWidth=(int)(dScaleX*iWidth);
                  iLength=(int)(iLength*dScaleY);
         }
         StretchDIBits(hDC,iX,iY,iWidth,iLength,0,0,lpbi->biWidth,lpbi->biHeight,(LPBYTE)lpbi                     // address for bitmap bits
                   + (bi.biSize + nColors * sizeof(RGBQUAD)),(LPBITMAPINFO)lpbi,DIB_RGB_COLORS,SRCCOPY);
         SelectPalette(hDC1,hPal,FALSE);
         ::ReleaseDC(NULL,hDC1);
         DeleteObject(hDIB);
         DeleteObject(hPal);
}
// 附:得到一个DC位图的代码
HBITMAP GetSrcBit(HDC hDC,DWORD BitWidth, DWORD BitHeight)
{
         HDC hBufDC;
         HBITMAP hBitmap, hBitTemp;
         hBufDC = CreateCompatibleDC(hDC);
         hBitmap = CreateCompatibleBitmap(hDC, BitWidth, BitHeight);
         hBitTemp = (HBITMAP) SelectObject(hBufDC, hBitmap);
         StretchBlt(hBufDC, 0, 0, BitWidth, BitHeight,
                   hDC, 0, 0, BitWidth, BitHeight, SRCCOPY);
         hBitmap = (HBITMAP) SelectObject(hBufDC, hBitTemp);
         ::DeleteDC(hBufDC);
         return hBitmap;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/bqw2008/archive/2008/12/25/3606158.aspx
http://blog.sina.com.cn/s/blog_4b44e1c00100g4ed.html