MFC:如何将 DI 位图打印到打印机?
MFC: How do you print a DI Bitmap to the printer?
我正在使用 MFC 并尝试使用 OnPrint()
来打印 DI 位图的内容。我知道如何获取我的位图,我知道 ::StretchDIBit
可以访问 DC,但要做到这一点,我需要知道纸张大小并想知道正常位图大小是否适合,就使用它,如果太大了,把它变小。但是我从哪里得到页面大小呢?如何将我的 DI 位图宽度/高度与打印机页面的输出相关联?
将::StretchDIBit
发送到一些随机值进行测试:
pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(500, 500);
pDC->SetViewportExt(4500, 6500);
打印出来了,但拉得不成比例。如果我只是简单地将它发送到 __super::OnPrint()
,它会打印出来但非常小。我宁愿让它只使用 OnDraw()
输出到屏幕很好,这就是 __super::OnPrint()
所做的,但是我如何设置它以打印正确的大小和比例?
TIA!!
编辑:
根据下面的回答,它没有用。什么都没有打印。如果我在 CView
(不打印)上显示时使用 MM_ISOTROPIC,则什么也没有显示,所以我很生气有条件的地图模式。这是完整的代码,包括 CView
window 中支持的缩放。什么是 missing/wrong?
TIA!!
void CMyImageView::OnDraw(CDC* pDCView)
{
if (m_DIBData != NULL) {
#define PALSIZE(x) ((x) > 8? 0: 1 << (x))
// move different versions of bitmap header to bitmap structure
BITMAP bm;
if (m_DIBData->biSize == sizeof(BITMAPCOREHEADER)) {
bm.bmWidth=((BITMAPCOREHEADER*)m_DIBData)->bcWidth;
bm.bmHeight=((BITMAPCOREHEADER*)m_DIBData)->bcHeight;
bm.bmBitsPixel=((BITMAPCOREHEADER*)m_DIBData)->bcBitCount;
bm.bmType=BI_RGB;
bm.bmBits=PBYTE(m_DIBData) + m_DIBData->biSize + PALSIZE(bm.bmBitsPixel) * 3;
}
else {
bm.bmWidth=m_DIBData->biWidth;
bm.bmHeight=m_DIBData->biHeight;
bm.bmBitsPixel=m_DIBData->biBitCount;
bm.bmType=m_DIBData->biCompression;
long color=m_DIBData->biClrUsed ? m_DIBData->biClrUsed : PALSIZE(bm.bmBitsPixel);
bm.bmBits=PBYTE(m_DIBData) + m_DIBData->biSize + color * 4;
}
CPoint point=GetScrollPosition();
CRect rcClient(0, 0, 0, 0);
if(pDCView->IsPrinting())
{
pDCView->SetMapMode(MM_ISOTROPIC);
pDCView->SetWindowExt(bm.bmWidth, bm.bmHeight);
rcClient.right=pDCView->GetDeviceCaps(HORZRES);
rcClient.bottom=pDCView->GetDeviceCaps(VERTRES);
// setup view
pDCView->SetViewportExt(rcClient.right, rcClient.bottom);
}
else {
ASSERT(MM_TEXT == pDCView->GetMapMode());
ASSERT(CPoint(0, 0) == pDCView->GetViewportOrg());
GetClientRect(rcClient);
}
const int cx=rcClient.right; // view client area width
const int cy=rcClient.bottom; // view client area height
const int bx=bm.bmWidth; // source bitmap width
const int by=bm.bmHeight; // source bitmap height
const int vx=(int)(bx * m_fZoom); // virtual document width
const int vy=(int)(by * m_fZoom); // virtual document height
const int xPos=point.x; // horizontal scroll position
const int yPos=point.y; // vertical scroll position
// source and destination coordinates and sizes
int xSrc, ySrc, nSrcWidth, nSrcHeight, xDst, yDst, nDstWidth, nDstHeight;
if (vx > cx) {
xSrc=(int)(xPos / m_fZoom);
nSrcWidth=bx - xSrc;
xDst=0;
nDstWidth=vx - xPos;
}
else {
xSrc=0;
nSrcWidth=bx;
xDst=cx / 2 - vx / 2;
nDstWidth=vx;
}
if (vy > cy) {
ySrc=0;
nSrcHeight=by;
yDst=-yPos;
nDstHeight=vy;
}
else {
ySrc=0;
nSrcHeight=by;
yDst=cy / 2 - vy / 2;
nDstHeight=vy;
}
::StretchDIBits(pDCView->m_hDC,
xDst, yDst, // xy-coordinates of upper-left corner of dest. rect.
nDstWidth, nDstHeight, // width & height of destination rectangle
xSrc, ySrc, // xy-coordinates of lower-left corner of source rect.
nSrcWidth, nSrcHeight, // width & height of source rectangle
bm.bmBits, // address of array with DIB bits
(BITMAPINFO*)m_DIBData, // address of structure with bitmap info
DIB_RGB_COLORS, // usage flags
SRCCOPY); // raster operation code
}
}
编辑:
所以我将上面的IsPrinting
部分修改为:
if(pDCView->IsPrinting())
{
pDCView->SetMapMode(MM_ISOTROPIC);
// setup base size of item
pDCView->SetWindowExt(bm.bmWidth, bm.bmHeight);
rcClient.right=bm.bmWidth;
rcClient.bottom=bm.bmHeight;
// setup view output to full page
int horzres=pDCView->GetDeviceCaps(HORZRES);
int vertres=pDCView->GetDeviceCaps(VERTRES);
pDCView->SetViewportExt(horzres, vertres);
}
成功了!但是现在我不得不在另一个问题中询问位图和精度输出。
答案是:
void CMyImageView::OnDraw(CDC* pDCView)
{
if (m_DIBData != NULL) {
#define PALSIZE(x) ((x) > 8? 0: 1 << (x))
// move different versions of bitmap header to bitmap structure
BITMAP bm;
if (m_DIBData->biSize == sizeof(BITMAPCOREHEADER)) {
bm.bmWidth=((BITMAPCOREHEADER*)m_DIBData)->bcWidth;
bm.bmHeight=((BITMAPCOREHEADER*)m_DIBData)->bcHeight;
bm.bmBitsPixel=((BITMAPCOREHEADER*)m_DIBData)->bcBitCount;
bm.bmType=BI_RGB;
bm.bmBits=PBYTE(m_DIBData) + m_DIBData->biSize + PALSIZE(bm.bmBitsPixel) * 3;
}
else {
bm.bmWidth=m_DIBData->biWidth;
bm.bmHeight=m_DIBData->biHeight;
bm.bmBitsPixel=m_DIBData->biBitCount;
bm.bmType=m_DIBData->biCompression;
long color=m_DIBData->biClrUsed ? m_DIBData->biClrUsed : PALSIZE(bm.bmBitsPixel);
bm.bmBits=PBYTE(m_DIBData) + m_DIBData->biSize + color * 4;
}
CPoint point=GetScrollPosition();
CRect rcClient(0, 0, 0, 0);
if(pDCView->IsPrinting())
{
pDCView->SetMapMode(MM_ISOTROPIC);
// setup base size of item
pDCView->SetWindowExt(bm.bmWidth, bm.bmHeight);
rcClient.right=bm.bmWidth;
rcClient.bottom=bm.bmHeight;
// setup view output to full page
int horzres=pDCView->GetDeviceCaps(HORZRES);
int vertres=pDCView->GetDeviceCaps(VERTRES);
pDCView->SetViewportExt(horzres, vertres);
}
else {
ASSERT(MM_TEXT == pDCView->GetMapMode());
ASSERT(CPoint(0, 0) == pDCView->GetViewportOrg());
GetClientRect(rcClient);
}
const int cx=rcClient.right; // view client area width
const int cy=rcClient.bottom; // view client area height
const int bx=bm.bmWidth; // source bitmap width
const int by=bm.bmHeight; // source bitmap height
const int vx=(int)(bx * m_fZoom); // virtual document width
const int vy=(int)(by * m_fZoom); // virtual document height
const int xPos=point.x; // horizontal scroll position
const int yPos=point.y; // vertical scroll position
// source and destination coordinates and sizes
int xSrc, ySrc, nSrcWidth, nSrcHeight, xDst, yDst, nDstWidth, nDstHeight;
if (vx > cx) {
xSrc=(int)(xPos / m_fZoom);
nSrcWidth=bx - xSrc;
xDst=0;
nDstWidth=vx - xPos;
}
else {
xSrc=0;
nSrcWidth=bx;
xDst=cx / 2 - vx / 2;
nDstWidth=vx;
}
if (vy > cy) {
ySrc=0;
nSrcHeight=by;
yDst=-yPos;
nDstHeight=vy;
}
else {
ySrc=0;
nSrcHeight=by;
yDst=cy / 2 - vy / 2;
nDstHeight=vy;
}
::StretchDIBits(pDCView->m_hDC,
xDst, yDst, // xy-coordinates of upper-left corner of dest. rect.
nDstWidth, nDstHeight, // width & height of destination rectangle
xSrc, ySrc, // xy-coordinates of lower-left corner of source rect.
nSrcWidth, nSrcHeight, // width & height of source rectangle
bm.bmBits, // address of array with DIB bits
(BITMAPINFO*)m_DIBData, // address of structure with bitmap info
DIB_RGB_COLORS, // usage flags
SRCCOPY); // raster operation code
}
}
我正在使用 MFC 并尝试使用 OnPrint()
来打印 DI 位图的内容。我知道如何获取我的位图,我知道 ::StretchDIBit
可以访问 DC,但要做到这一点,我需要知道纸张大小并想知道正常位图大小是否适合,就使用它,如果太大了,把它变小。但是我从哪里得到页面大小呢?如何将我的 DI 位图宽度/高度与打印机页面的输出相关联?
将::StretchDIBit
发送到一些随机值进行测试:
pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(500, 500);
pDC->SetViewportExt(4500, 6500);
打印出来了,但拉得不成比例。如果我只是简单地将它发送到 __super::OnPrint()
,它会打印出来但非常小。我宁愿让它只使用 OnDraw()
输出到屏幕很好,这就是 __super::OnPrint()
所做的,但是我如何设置它以打印正确的大小和比例?
TIA!!
编辑:
根据下面的回答,它没有用。什么都没有打印。如果我在 CView
(不打印)上显示时使用 MM_ISOTROPIC,则什么也没有显示,所以我很生气有条件的地图模式。这是完整的代码,包括 CView
window 中支持的缩放。什么是 missing/wrong?
TIA!!
void CMyImageView::OnDraw(CDC* pDCView)
{
if (m_DIBData != NULL) {
#define PALSIZE(x) ((x) > 8? 0: 1 << (x))
// move different versions of bitmap header to bitmap structure
BITMAP bm;
if (m_DIBData->biSize == sizeof(BITMAPCOREHEADER)) {
bm.bmWidth=((BITMAPCOREHEADER*)m_DIBData)->bcWidth;
bm.bmHeight=((BITMAPCOREHEADER*)m_DIBData)->bcHeight;
bm.bmBitsPixel=((BITMAPCOREHEADER*)m_DIBData)->bcBitCount;
bm.bmType=BI_RGB;
bm.bmBits=PBYTE(m_DIBData) + m_DIBData->biSize + PALSIZE(bm.bmBitsPixel) * 3;
}
else {
bm.bmWidth=m_DIBData->biWidth;
bm.bmHeight=m_DIBData->biHeight;
bm.bmBitsPixel=m_DIBData->biBitCount;
bm.bmType=m_DIBData->biCompression;
long color=m_DIBData->biClrUsed ? m_DIBData->biClrUsed : PALSIZE(bm.bmBitsPixel);
bm.bmBits=PBYTE(m_DIBData) + m_DIBData->biSize + color * 4;
}
CPoint point=GetScrollPosition();
CRect rcClient(0, 0, 0, 0);
if(pDCView->IsPrinting())
{
pDCView->SetMapMode(MM_ISOTROPIC);
pDCView->SetWindowExt(bm.bmWidth, bm.bmHeight);
rcClient.right=pDCView->GetDeviceCaps(HORZRES);
rcClient.bottom=pDCView->GetDeviceCaps(VERTRES);
// setup view
pDCView->SetViewportExt(rcClient.right, rcClient.bottom);
}
else {
ASSERT(MM_TEXT == pDCView->GetMapMode());
ASSERT(CPoint(0, 0) == pDCView->GetViewportOrg());
GetClientRect(rcClient);
}
const int cx=rcClient.right; // view client area width
const int cy=rcClient.bottom; // view client area height
const int bx=bm.bmWidth; // source bitmap width
const int by=bm.bmHeight; // source bitmap height
const int vx=(int)(bx * m_fZoom); // virtual document width
const int vy=(int)(by * m_fZoom); // virtual document height
const int xPos=point.x; // horizontal scroll position
const int yPos=point.y; // vertical scroll position
// source and destination coordinates and sizes
int xSrc, ySrc, nSrcWidth, nSrcHeight, xDst, yDst, nDstWidth, nDstHeight;
if (vx > cx) {
xSrc=(int)(xPos / m_fZoom);
nSrcWidth=bx - xSrc;
xDst=0;
nDstWidth=vx - xPos;
}
else {
xSrc=0;
nSrcWidth=bx;
xDst=cx / 2 - vx / 2;
nDstWidth=vx;
}
if (vy > cy) {
ySrc=0;
nSrcHeight=by;
yDst=-yPos;
nDstHeight=vy;
}
else {
ySrc=0;
nSrcHeight=by;
yDst=cy / 2 - vy / 2;
nDstHeight=vy;
}
::StretchDIBits(pDCView->m_hDC,
xDst, yDst, // xy-coordinates of upper-left corner of dest. rect.
nDstWidth, nDstHeight, // width & height of destination rectangle
xSrc, ySrc, // xy-coordinates of lower-left corner of source rect.
nSrcWidth, nSrcHeight, // width & height of source rectangle
bm.bmBits, // address of array with DIB bits
(BITMAPINFO*)m_DIBData, // address of structure with bitmap info
DIB_RGB_COLORS, // usage flags
SRCCOPY); // raster operation code
}
}
编辑:
所以我将上面的IsPrinting
部分修改为:
if(pDCView->IsPrinting())
{
pDCView->SetMapMode(MM_ISOTROPIC);
// setup base size of item
pDCView->SetWindowExt(bm.bmWidth, bm.bmHeight);
rcClient.right=bm.bmWidth;
rcClient.bottom=bm.bmHeight;
// setup view output to full page
int horzres=pDCView->GetDeviceCaps(HORZRES);
int vertres=pDCView->GetDeviceCaps(VERTRES);
pDCView->SetViewportExt(horzres, vertres);
}
成功了!但是现在我不得不在另一个问题中询问位图和精度输出。
答案是:
void CMyImageView::OnDraw(CDC* pDCView)
{
if (m_DIBData != NULL) {
#define PALSIZE(x) ((x) > 8? 0: 1 << (x))
// move different versions of bitmap header to bitmap structure
BITMAP bm;
if (m_DIBData->biSize == sizeof(BITMAPCOREHEADER)) {
bm.bmWidth=((BITMAPCOREHEADER*)m_DIBData)->bcWidth;
bm.bmHeight=((BITMAPCOREHEADER*)m_DIBData)->bcHeight;
bm.bmBitsPixel=((BITMAPCOREHEADER*)m_DIBData)->bcBitCount;
bm.bmType=BI_RGB;
bm.bmBits=PBYTE(m_DIBData) + m_DIBData->biSize + PALSIZE(bm.bmBitsPixel) * 3;
}
else {
bm.bmWidth=m_DIBData->biWidth;
bm.bmHeight=m_DIBData->biHeight;
bm.bmBitsPixel=m_DIBData->biBitCount;
bm.bmType=m_DIBData->biCompression;
long color=m_DIBData->biClrUsed ? m_DIBData->biClrUsed : PALSIZE(bm.bmBitsPixel);
bm.bmBits=PBYTE(m_DIBData) + m_DIBData->biSize + color * 4;
}
CPoint point=GetScrollPosition();
CRect rcClient(0, 0, 0, 0);
if(pDCView->IsPrinting())
{
pDCView->SetMapMode(MM_ISOTROPIC);
// setup base size of item
pDCView->SetWindowExt(bm.bmWidth, bm.bmHeight);
rcClient.right=bm.bmWidth;
rcClient.bottom=bm.bmHeight;
// setup view output to full page
int horzres=pDCView->GetDeviceCaps(HORZRES);
int vertres=pDCView->GetDeviceCaps(VERTRES);
pDCView->SetViewportExt(horzres, vertres);
}
else {
ASSERT(MM_TEXT == pDCView->GetMapMode());
ASSERT(CPoint(0, 0) == pDCView->GetViewportOrg());
GetClientRect(rcClient);
}
const int cx=rcClient.right; // view client area width
const int cy=rcClient.bottom; // view client area height
const int bx=bm.bmWidth; // source bitmap width
const int by=bm.bmHeight; // source bitmap height
const int vx=(int)(bx * m_fZoom); // virtual document width
const int vy=(int)(by * m_fZoom); // virtual document height
const int xPos=point.x; // horizontal scroll position
const int yPos=point.y; // vertical scroll position
// source and destination coordinates and sizes
int xSrc, ySrc, nSrcWidth, nSrcHeight, xDst, yDst, nDstWidth, nDstHeight;
if (vx > cx) {
xSrc=(int)(xPos / m_fZoom);
nSrcWidth=bx - xSrc;
xDst=0;
nDstWidth=vx - xPos;
}
else {
xSrc=0;
nSrcWidth=bx;
xDst=cx / 2 - vx / 2;
nDstWidth=vx;
}
if (vy > cy) {
ySrc=0;
nSrcHeight=by;
yDst=-yPos;
nDstHeight=vy;
}
else {
ySrc=0;
nSrcHeight=by;
yDst=cy / 2 - vy / 2;
nDstHeight=vy;
}
::StretchDIBits(pDCView->m_hDC,
xDst, yDst, // xy-coordinates of upper-left corner of dest. rect.
nDstWidth, nDstHeight, // width & height of destination rectangle
xSrc, ySrc, // xy-coordinates of lower-left corner of source rect.
nSrcWidth, nSrcHeight, // width & height of source rectangle
bm.bmBits, // address of array with DIB bits
(BITMAPINFO*)m_DIBData, // address of structure with bitmap info
DIB_RGB_COLORS, // usage flags
SRCCOPY); // raster operation code
}
}