Home

MFC Topics: CDC Printing Fundamentals

 

Introduction

So far, we have introduced and used CDC as the class used to draw text or graphics in a view. As we saw in the previous section, the CDC class also highly intervenes when it comes to printing. Microsoft Windows considers different types of drawing, depending on the device that is showing the result. The screen of a monitor is usually referred to as a display. Because the printer is an external device, it has its own category.

Because it distinguishes the display and the printer, the CView class provides two messages and events to deal with drawing. Since you can and will usually implement both events, you may want to know which one gets fired and when. Consider the following two events:

void CDecorationView::OnDraw(CDC* pDC)
{
	CDecorationDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	AfxMessageBox("Calling OnDraw())");

	// TODO: add draw code for native data here
}

void CDecorationView::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: Add your message handler code here
	// Do not call CView::OnPaint() for painting messages

	AfxMessageBox("Calling OnPaint())");
}

If you execute the application, when it appears, a message box indicates that the OnPaint event is fired. If, on the main menu, you click File -> Print… and, in the Print dialog box, you click OK, you would notice that the OnDraw event fires. This indicates that the OnPaint event is used to draw on the monitor and the OnDraw event is used to draw on the piece of paper on the printer.

Consider the following code:

void CDecorationView::OnDraw(CDC* pDC)
{
	CDecorationDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return; 

	AfxMessageBox("Calling OnDraw())");

	// TODO: add draw code for native data here
	
	CBitmap bmpFlower;
	CDC memDCFlower;

	bmpFlower.LoadBitmap(IDB_FLOWER1);
	memDCFlower.CreateCompatibleDC(pDC);
	CBitmap *bmpPrevious = memDCFlower.SelectObject(&bmpFlower);

	pDC->BitBlt(10, 10, 450, 563, &memDCFlower, 0, 0, SRCCOPY);

	pDC->SelectObject(bmpPrevious);
}

void CDecorationView::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: Add your message handler code here
	// Do not call CView::OnPaint() for painting messages

	AfxMessageBox("Calling OnPaint())");
}

This time, if you execute the application, the OnPaint event would fire but nothing displays on the screen. If, on the main menu, you click File -> Print… and if, on the Print dialog box, you click OK, the OnDraw event would fire and a small picture would be printed on the paper.

Consider the following events:

void CDecorationView::OnDraw(CDC* pDC)
{
	CDecorationDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: add draw code for native data here
	CBitmap bmpFlower;
	CDC memDCFlower;

	bmpFlower.LoadBitmap(IDB_FLOWER1);
	memDCFlower.CreateCompatibleDC(pDC);
	CBitmap *bmpPrevious = memDCFlower.SelectObject(&bmpFlower);

	pDC->BitBlt(10, 10, 450, 563, &memDCFlower, 0, 0, SRCCOPY);

	pDC->SelectObject(bmpPrevious);
} 

void CDecorationView::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: Add your message handler code here
	// Do not call CView::OnPaint() for painting messages
	CBitmap bmpFlower;
	CDC memDCFlower;

	bmpFlower.LoadBitmap(IDB_FLOWER1);
	memDCFlower.CreateCompatibleDC(&dc);
	CBitmap *bmpPrevious = memDCFlower.SelectObject(&bmpFlower);

	dc.BitBlt(10, 10, 450, 563, &memDCFlower, 0, 0, SRCCOPY);

	dc.SelectObject(bmpPrevious);
}

Notice that both events received the exact same code. If you execute the application, the OnPaint event would fire and a large picture would be drawn on the screen. If you print, the OnDraw event would fire and a small picture would be printed on the paper although both events received the same code. This illustrates that the “display” and the “printer” interpret drawing differently

Transforming the Printer

We have just established that the display and the printer interpret GDI code differently. This means that we should also draw on them differently. Because they are rendering the same contents when they receive the same code, since the result on the printer simply appears small, we can simply “zoom” it to a reasonable size to make it appear as the same contents of the display. In our study of the GDI library, we saw that, to increase the display size of a drawing, we could call the CDC::SetViewportExt() method after calling the CDC::SetWindowExt() method and the CDC::SetMapMode() method with a value of MM_ISOTROPIC.

Here is an example:

void CDecorationView::OnDraw(CDC* pDC)
{
	CDecorationDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: add draw code for native data here
	CBitmap bmpFlower;
	CDC memDCFlower;

	bmpFlower.LoadBitmap(IDB_FLOWER1);
	memDCFlower.CreateCompatibleDC(pDC);
	CBitmap *bmpPrevious = memDCFlower.SelectObject(&bmpFlower);

	pDC->SetMapMode(MM_ISOTROPIC);
	pDC->SetWindowExt(500, 500);
	pDC->SetViewportExt(4500, 5630);

	pDC->BitBlt(10, 10, 450, 563, &memDCFlower, 0, 0, SRCCOPY);

	pDC->SelectObject(bmpPrevious);
}

void CDecorationView::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: Add your message handler code here
	// Do not call CView::OnPaint() for painting messages
	CBitmap bmpFlower;
	CDC memDCFlower;

	bmpFlower.LoadBitmap(IDB_FLOWER1);
	memDCFlower.CreateCompatibleDC(&dc);
	CBitmap *bmpPrevious = memDCFlower.SelectObject(&bmpFlower);

	dc.BitBlt(10, 10, 450, 563, &memDCFlower, 0, 0, SRCCOPY);

	dc.SelectObject(bmpPrevious);
}

This time, the printed sheet would resemble the picture on the view:

 

Previous Copyright © 2006-2007 FunctionX, Inc.