图形能在窗口显示,但是用打印机的句柄printDC.BitBlt画到打印机设备上就不能显示图片了 注:printDC.TextOut可以打印出字符

解决方案 »

  1.   

    标题     打印位图(上)    bluebohe(原作)  
      
    关键字     打印 位图 
      
           关于位图的打印,很多人对此很困惑,在这方面产生的问题也很多,主要包括以下几点。       1:打印的图片太小;       2:根本打印不出来位图       3:打印预览可见、但打印不出来;       产生这些问题的根本原因,在于对位图的理解不够深刻。       一个CBitmap对象,可能是DDB位图(设备相关位图),或者DIB位图(设备无关位图),其中,一个设备兼容的内存DC中,只能选择该设备兼容的DDB位图或者单色的位图。注意,位图只能被选择进入到设备兼容的内存DC中,并不能选择进入到真实的dc中,这就是有时候根本打印不出来图片的原因。       至于打印图片太小的问题,主要是因为衡量位图大小的单位是横向和纵向的像素数,而不是确切的长度,所以如果把一个图片映射到屏幕上,会出现一个比较大的图像,但是打印机的分辨率比屏幕高很多(屏幕一般是96dpi,而打印机最少一般也有300dpi),如果把位图不缩放地映射到打印机上,则必然要小很多。解决该类问题的方法是使用StretchBlt拉伸显示图像。       另外LoadImage函数中使用LR_CREATEDIBSECTION选项产生的DIB位图可以被选择进入任何设备兼容的内存DC中。因此可以使用LoadImage函数加载一个位图文件或者资源,直接把位图通过StretchBlt打印出来。下面是把一个位图文件进行打印的相关代码:/*//打印或者在屏幕左上角上画位图文件//pDC 打印机或者屏幕dc指针iLogPixelXiLogPixelY屏幕DC的GetDeviceCaps(LOGPIXELSX)值,其中iLogPixelX=DC.GetDeviceCaps(LOGPIXELSX);iLogPixelY=DC.GetDeviceCaps(LOGPIXELSY);const char *strFileName BMP图片文件名称*/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上,下面是一个可以打印任何位图的函数代码。
     
      

  2.   

    标题     打印位图(下)    bluebohe(原作)  
      
    关键字     打印 位图 
      /*
    HDC hDC,                  打印机dcHBITMAP hBmp,         待打印位图int iX,                          位图的左上角点x坐标int iY,                           位图的左上角点y坐标double dScaleX,         打印机分辨率和屏幕分辨率x方向的比值,在没有指定位图显示高度和宽度的时候用的上double dScaleY,         打印机分辨率和屏幕分辨率y方向的比值,在没有指定位图显示高度和宽度的时候用的上int iWidth=0,         位图的显示宽度int iLength=0         位图的显示高度*/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;}  
      

  3.   

    void CPrintWndDlg::Print()
    {
    CDC printDC;
    CPrintDialog printDlg(FALSE);
    CDC dcMemory;
    DOCINFO docInfo; bitmap.LoadBitmap(IDB_BITMAP2); dcMemory.CreateCompatibleDC(&printDC);
        pOldBmp=dcMemory.SelectObject(&bitmap); if(printDlg.DoModal()==IDOK)
    {
    HDC hDC;
    hDC=printDlg.GetPrinterDC();
    if(!printDC.Attach(hDC))
    return;
    }
    else
    {
    printDC.Detach();
    return;
    }

    memset(&docInfo,0,sizeof(docInfo));
    docInfo.cbSize=sizeof(DOCINFO);
    docInfo.lpszDocName="Print Window";
    if(printDC.StartDoc(&docInfo)<=0)
    {
    #ifdef _DEBUG
    AfxMessageBox("Start Doc Failed");
    #endif
    printDC.Detach();
    return;
    }
    dcMemory.SelectObject(&bitmap);
    printDC.StartPage();
    printDC.SetMapMode(MM_HIENGLISH);

        printDC.BitBlt(0,0,1000,1000,&dcMemory,0,0,SRCCOPY);  
    printDC.EndPage();
    printDC.EndDoc(); printDC.Detach();}
    这个函数怎么改一下能把资源IDB_BITMAP2打印出来啊
      

  4.   

    虽然我的东西是粘来粘去的,可是却能解决你的问题,我也了解你的问题所在!
    你的错误是LoadBitmap是显示设备兼容的,而不是打印设备兼容的,所以我不用调试就知道你在打印的时候创建的打印设备兼容DC在SelectObject的时会报错误(打印预览不会报错,因为这也是显示设备)不信你查返回值。打印位图的话必须使用StretchDIBits才可以,上面的代码也是把显示设备兼容的位图转化成DIB位图然后打印到打印机的
      

  5.   

    不明白,既然你能找得到,那你为什么不使用网上的方法而使用自己错误的方法,好了好了,不跟你计较这些了使用上面的Draw函数只要传入你的打印机DC和你所LoadBitmap出来的bitmap就能够打印了。郁闷