I'm using MFC and trying to use OnPrint()
to print the contents of a DI Bitmap. I know how to get my bitmap, I know of ::StretchDIBit
to get to to a DC, but to do it, I need to know the paper size and want to say if normal bitmap size fits, just use that, if too big, make it smaller. But Where do I get the page size? How do I relate my DI bitmap width / height to the output to the printer page?
Sending the ::StretchDIBit
to some random values for testing:
pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(500, 500);
pDC->SetViewportExt(4500, 6500);
Printed but it was stretched out of proportion. If I just simply send it down to __super::OnPrint()
it prints but very tiny. I'd rather let it just use the OnDraw()
which outputs to the screen fine and that's what __super::OnPrint()
does, but how do I set it up to print the correct size and proportion?
TIA!!
EDIT:
Based on answer below, it didn't work. Nothing printed. If I used MM_ISOTROPIC when showing on the CView
(not printing) nothing was showing so I mad the map mode conditional. Here's the complete code including scaling supported in the CView
window. What is 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
}
}
Edit:
So I modified the IsPrinting
section above to be:
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);
}
It worked! But now I have to ask about bitmaps and precision output in a different question.
The answer is:
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
}
}