图像打印问题,困惑了很久的问题。 我用MFC做了一个打印程序,里面用CBitmap类画了一些图像,在Hp Laser Jet 6L 打印时却不能显示图像,但预览时一切正常。在其它打印机上也可以打印正常。请问为什么能正常预览却不能正常打印。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 好象不会吧,我的Bmp图像都是10k 左右。不过有多个。 可能是惠普打印机的驱动程序不好。我也曾碰到过你今天的问题,甚至还有同一台打印机在2000下能打印,在98或me下就不能打印。后在各种平和各种打印机环境下调试才找到根本原因: 不同的操作系统和不同的打印机对VC编程语句顺序的要求不同。 兼容最好的是2000,其次为98,最次为me;不同的打印机,对在程序中设置自定义页的要求不同。 最后的处理方法是: 1.不要用自定义页;只要定义一张够大的纸就行。 2.打印语句顺序不能简化; CPrintDialog mypd(0);//构造打印设置对话框对象,但不显示 mypd.DoModal(); mypd.GetDefaults(); // 检取缺省打印设备的设备环境 DEVMODE * dm = mypd.GetDevMode();// 提取缺省打印机的DEVMODE数据 CDC dc; dc.CreateDC(drivername1,devicename1,outputname1,dm);// 用修改过的初始值构造新的DC DOCINFO * di = new DOCINFO ;// 构造文档信息结构 di->lpszDocName = "打印任务名";// 初始化文档信息结构为开始打印作准备 di->lpszOutput = NULL ; di->fwType = DI_APPBANDING; // 设置最佳打印 dc.StartDoc(di) ; // 开始打印作业 CBrush brush; //这个刷了 brush.CreateSolidBrush(RGB(0,0,0)); //不能少 dc.StartPage(); // 开始页 dc.SetMapMode(MM_HIMETRIC) ;// 设置打印机的映射模式(这句不能在开始页前) dc.SelectObject(&pen); dc.SelectObject(&brush);// 在此实现一打印任务 dc.EndDoc(); // 结束一个打印任务 dc.AbortDoc(); // 中断打印任务 dc.Detach(); // 释放打印 DC dc.DeleteDC(); 打印图像不能直接用BitBlt等DDB函数,用如下函数即可:BOOL printbmp(CDC *pDC, int x, int y, int width, int height, HBITMAP hbmp){ BITMAPINFO *pinfo = BitmapToDIB(NULL, hbmp, 24, 0); if(pinfo) { int nHeadSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * GetDIBColorCount(pinfo->bmiHeader); BYTE *pbits = (BYTE *)pinfo + nHeadSize; SetStretchBltMode(pDC->m_hDC, STRETCH_HALFTONE);//COLORONCOLOR); StretchDIBits(pDC->m_hDC, x, y, width, height, 0, 0, pinfo->bmiHeader.biWidth, pinfo->bmiHeader.biHeight, pbits, pinfo, DIB_RGB_COLORS, SRCCOPY); delete [](BYTE *)pinfo; return TRUE; } return FALSE;}int GetDIBPixelSize(const BITMAPINFOHEADER & bmih){ if ( bmih.biSizeImage ) return bmih.biSizeImage; else return ( bmih.biWidth * bmih.biBitCount + 31 ) / 32 * 4 * bmih.biPlanes * abs(bmih.biHeight);}int GetDIBColorCount(const BITMAPINFOHEADER & bmih){ if ( bmih.biBitCount <= 8 ) if ( bmih.biClrUsed ) return bmih.biClrUsed; else return 1 << bmih.biBitCount; else if ( bmih.biCompression==BI_BITFIELDS ) return 3 + bmih.biClrUsed; else return bmih.biClrUsed;}BITMAPINFO *BitmapToDIB( HPALETTE hPal, // 调色板 HBITMAP hBmp, // HBITMAP DDB int nBitCount, // 颜色位数 int nCompression) // 压缩模式{ typedef struct { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[256+3]; } DIBINFO; BITMAP ddbinfo; DIBINFO dibinfo; // retrieve DDB information if ( GetObject(hBmp, sizeof(BITMAP), & ddbinfo)==0 ) return NULL; // fill out BITMAPINFOHEADER based on size and required format memset(&dibinfo, 0, sizeof(dibinfo)); dibinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); dibinfo.bmiHeader.biWidth = ddbinfo.bmWidth; dibinfo.bmiHeader.biHeight = ddbinfo.bmHeight; dibinfo.bmiHeader.biPlanes = 1; dibinfo.bmiHeader.biBitCount = nBitCount; dibinfo.bmiHeader.biCompression = nCompression; HDC hDC = GetDC(NULL); // screen DC HGDIOBJ hpalOld; if ( hPal ) hpalOld = SelectPalette(hDC, hPal, FALSE); else hpalOld = NULL; // query GDI for image size GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, NULL, (BITMAPINFO *) & dibinfo, DIB_RGB_COLORS); int nInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * GetDIBColorCount(dibinfo.bmiHeader); int nTotalSize = nInfoSize + GetDIBPixelSize(dibinfo.bmiHeader); BYTE * pDIB = new BYTE[nTotalSize]; if ( pDIB ) { memcpy(pDIB, & dibinfo, nInfoSize); if ( ddbinfo.bmHeight != GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, pDIB + nInfoSize, (BITMAPINFO *) pDIB, DIB_RGB_COLORS) ) { delete [] pDIB; pDIB = NULL; } } if ( hpalOld ) SelectObject(hDC, hpalOld); ReleaseDC(NULL, hDC); return (BITMAPINFO *) pDIB;} 我把DC设置为MM_LOWERTES的映射模式,并调用:printbmp(CDC *pDC, int x, int y, int width, int height, HBITMAP hbmp)函数打打印,但在预览时图像显得很小,比屏幕布上显示的小很多。 我的情况和ljxxjl的情形类似,在2000下打印正常。在98下文字正常,小图片也正常(使用StretchDIBits方式打印图片的),图像大一点,A4横向的一半左右就不出错误了。预览方式是每问题的。很是奇怪? VC技术内幕中的CDib可以解决这个问题 简单GetFieldValue取值 如何把自定义按钮的外观设置为自己想要的图标(bitmap)? 紧急求助@@@@@@@@@ 使用insert into后怎么样得到刚插入记录的ID. 我的机子中了恶意程序 编译问题,很急! 高手呢?我想在RichEdit中插入OlE对象,怎么做?Up有分! 哪儿有vc7.0下载? 在一个循环内如何响应运行界面的按键信息 好找工作吗 我的非模态对话框怎么关不掉?? 请问自己写的程序只能在少数机子上运行正常时该怎么处理?
不同的操作系统和不同的打印机对VC编程语句顺序的要求不同。
兼容最好的是2000,其次为98,最次为me;不同的打印机,对在程序中设置自定义页的要求不同。
最后的处理方法是:
1.不要用自定义页;只要定义一张够大的纸就行。
2.打印语句顺序不能简化;
CPrintDialog mypd(0);//构造打印设置对话框对象,但不显示 mypd.DoModal();
mypd.GetDefaults(); // 检取缺省打印设备的设备环境
DEVMODE * dm = mypd.GetDevMode();// 提取缺省打印机的DEVMODE数据
CDC dc;
dc.CreateDC(drivername1,devicename1,outputname1,dm);// 用修改过的初始值构造新的DC
DOCINFO * di = new DOCINFO ;// 构造文档信息结构
di->lpszDocName = "打印任务名";// 初始化文档信息结构为开始打印作准备
di->lpszOutput = NULL ;
di->fwType = DI_APPBANDING; // 设置最佳打印
dc.StartDoc(di) ; // 开始打印作业 CBrush brush; //这个刷了
brush.CreateSolidBrush(RGB(0,0,0)); //不能少
dc.StartPage(); // 开始页
dc.SetMapMode(MM_HIMETRIC) ;// 设置打印机的映射模式(这句不能在开始页前)
dc.SelectObject(&pen);
dc.SelectObject(&brush);// 在此实现一打印任务 dc.EndDoc(); // 结束一个打印任务
dc.AbortDoc(); // 中断打印任务
dc.Detach(); // 释放打印 DC
dc.DeleteDC();
{
BITMAPINFO *pinfo = BitmapToDIB(NULL, hbmp, 24, 0);
if(pinfo)
{
int nHeadSize = sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * GetDIBColorCount(pinfo->bmiHeader);
BYTE *pbits = (BYTE *)pinfo + nHeadSize; SetStretchBltMode(pDC->m_hDC, STRETCH_HALFTONE);//COLORONCOLOR);
StretchDIBits(pDC->m_hDC, x, y, width, height,
0, 0, pinfo->bmiHeader.biWidth, pinfo->bmiHeader.biHeight,
pbits, pinfo, DIB_RGB_COLORS, SRCCOPY); delete [](BYTE *)pinfo;
return TRUE;
}
return FALSE;
}
int GetDIBPixelSize(const BITMAPINFOHEADER & bmih)
{
if ( bmih.biSizeImage )
return bmih.biSizeImage;
else
return ( bmih.biWidth * bmih.biBitCount + 31 ) / 32 * 4 * bmih.biPlanes * abs(bmih.biHeight);
}
int GetDIBColorCount(const BITMAPINFOHEADER & bmih)
{
if ( bmih.biBitCount <= 8 )
if ( bmih.biClrUsed )
return bmih.biClrUsed;
else
return 1 << bmih.biBitCount;
else if ( bmih.biCompression==BI_BITFIELDS )
return 3 + bmih.biClrUsed;
else
return bmih.biClrUsed;
}
BITMAPINFO *BitmapToDIB( HPALETTE hPal, // 调色板
HBITMAP hBmp, // HBITMAP DDB
int nBitCount, // 颜色位数
int nCompression) // 压缩模式
{
typedef struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256+3];
} DIBINFO; BITMAP ddbinfo;
DIBINFO dibinfo; // retrieve DDB information
if ( GetObject(hBmp, sizeof(BITMAP), & ddbinfo)==0 )
return NULL; // fill out BITMAPINFOHEADER based on size and required format
memset(&dibinfo, 0, sizeof(dibinfo)); dibinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dibinfo.bmiHeader.biWidth = ddbinfo.bmWidth;
dibinfo.bmiHeader.biHeight = ddbinfo.bmHeight;
dibinfo.bmiHeader.biPlanes = 1;
dibinfo.bmiHeader.biBitCount = nBitCount;
dibinfo.bmiHeader.biCompression = nCompression; HDC hDC = GetDC(NULL); // screen DC
HGDIOBJ hpalOld;
if ( hPal )
hpalOld = SelectPalette(hDC, hPal, FALSE);
else
hpalOld = NULL; // query GDI for image size
GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, NULL, (BITMAPINFO *) & dibinfo, DIB_RGB_COLORS); int nInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * GetDIBColorCount(dibinfo.bmiHeader);
int nTotalSize = nInfoSize + GetDIBPixelSize(dibinfo.bmiHeader); BYTE * pDIB = new BYTE[nTotalSize]; if ( pDIB )
{
memcpy(pDIB, & dibinfo, nInfoSize);
if ( ddbinfo.bmHeight != GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, pDIB + nInfoSize, (BITMAPINFO *) pDIB, DIB_RGB_COLORS) )
{
delete [] pDIB;
pDIB = NULL;
}
} if ( hpalOld )
SelectObject(hDC, hpalOld); ReleaseDC(NULL, hDC); return (BITMAPINFO *) pDIB;
}
printbmp(CDC *pDC, int x, int y, int width, int height, HBITMAP hbmp)
函数打打印,但在预览时图像显得很小,比屏幕布上显示的小很多。