Click here to Skip to main content
15,881,882 members
Articles / Desktop Programming / MFC

Very Simple Print Preview without the Doc/View Architecture

Rate me:
Please Sign up or sign in to vote.
4.45/5 (7 votes)
9 Aug 2001 116.7K   3K   35   12
A very simple way of displaying a print preview in a simple window

Introduction

The Doc/View architecture in MFC is not the fastest way to create a simple print preview. This article will explain how to create your own print preview.

MFC Doc/View is designed to make the MSVC programmers get their work done in minutes, including print preview. Sometimes, we do not need to use Doc/View framework but we really do need its print-preview power.

The key to Print Preview is in the following functions:

  • CreateCompatibleBitmap
  • CreateCompatibleDC
  • GetDeviceCaps
  • GetTextExtent

Besides those four functions, Print Preview needs a function that will work for scaling and painting on the screen DC.

Luckily, we have StretchBlt and BitBlt ready to do the dirty work, but sometimes StretchBlt might need to be replaced by your favourite routine (for dithering, filtering, antialiasing, etc.).

The function to perform print preview in a window is as follows:

C++
// pWnd is the window you wish to show the preview
// Design and implementation cinoban@yahoo.com 13 Jan 2000 15:14
//	Danang Suharno
//	Ngadinegaran MJ 3/156
//	Yogyakarta 55143
//	Indonesia
//
void PrintPreview(CWnd *pWnd) 
{
	CString strWords;
	CWnd* pWnd = GetDlgItem(IDC_STATIC_PREVIEW); // This is a rectangle control
	CDC* dc;
	CDC memoriDC;
	CBitmap memBMP;
	CBitmap* pOldBMP;
	CFont fnt;
	CFont* pOldFnt;
	CRect rect;
	CRect rectMemory;
	CSize zMetrix;

	//
	//
	//
	CPrintDialog pdlg(FALSE);
	DOCINFO di;
	CDC prnDC;

	di.cbSize = sizeof(DOCINFO);
	di.lpszDocName = "This string will appear in Printer Queue";
	di.lpszOutput = NULL;     
	di.lpszDatatype = NULL;
	di.fwType = 0;

	//
	// Get current printer setting
	//
	pdlg.GetDefaults();
	
	//
	dc = pWnd->GetDC();
	pWnd->GetClientRect(&rect);

	// DC printer???
	if( !prnDC.Attach(pdlg.GetPrinterDC()) )
		AfxMessageBox("Invalid Printer DC");

	memoriDC.CreateCompatibleDC(&prnDC); // Create DC for Preview

	//
	// Get the resolution of Screen and Current Default Printer
	//
	int iPrnX = prnDC.GetDeviceCaps(HORZRES);
	int iPrnY = prnDC.GetDeviceCaps(VERTRES);
	int iMonX = dc->GetDeviceCaps(HORZRES); // Device Target is Monitor
	int iMonY = dc->GetDeviceCaps(VERTRES);

	rectMemory.top = 0;
	rectMemory.left = 0;
	rectMemory.bottom = iPrnY;
	rectMemory.right = iPrnX;

	//
	// Create a Memory Bitmap that is compatible with the Printer DC
	// then select or make the bitmap as current GDI active object
	//
	memBMP.CreateCompatibleBitmap(&prnDC, rectMemory.Width(), rectMemory.Height());
	pOldBMP = memoriDC.SelectObject(&memBMP);

	//
	// Clear memory DC or in other words
	// paint the bitmap with white colour and transparent text
	//
	memoriDC.SetBkMode(TRANSPARENT);
	memoriDC.SetTextColor(RGB(0, 0, 0));
	memoriDC.PatBlt(0, 0, rectMemory.Width(), rectMemory.Height(), WHITENESS);

	//
	// Prepare the font
	//
	int iPointz = 100;
	fnt.CreatePointFont(iPointz, "OCR A", &memoriDC);
	strWords.Format("This is line number    ");        // Test string
	pOldFnt = memoriDC.SelectObject(&fnt);
	zMetrix = memoriDC.GetTextExtent(strWords);
	int iPos = 0;

	//
	// Write string or Paint something
	//
	int iMaksimal = 0;
	int iLineHeight = 1;
	int iLoop;
	CString strPuncak;

	//
	// Calculate how many lines we could fit
	//
	for(iLoop = 1; iLoop < 100; iLoop++)
	{
		if( ((zMetrix.cy+iLineHeight)*iLoop) < iPrnY ) 
			iMaksimal++;
	}

	strPuncak.Format("Maximum Amount of line(s) for %d points are %d lines", 
		iPointz, iMaksimal);
	
	//
	//
	//
	for(iLoop = 0; iLoop < iMaksimal; iLoop++)
	{
		strWords.Format("This is line %d", iLoop);
		memoriDC.TextOut(0, iLoop*(zMetrix.cy+iLineHeight), strWords);
	}
	
	//
	// Reseting font
	//
	memoriDC.SelectObject(pOldFnt);

	//
	// Calculate ratio
	//
	float fXRatio = (float) iMonX/iPrnX;
	float fYRatio = (float) iMonY/iPrnY;	
	
	//  iLebar = Width
	//  iTinggi = Height
	//  iXPosisiPreview = horizontal location of preview
	//  iYPosisiPreview = vertical location of preview
	//
	int iLebar = rect.Width()*fXRatio;
	int iTinggi = rect.Height()*fYRatio;
	int iXPosisiPreview = (rect.Width() - iLebar)/2;
	int iYPosisiPreview = (rect.Height() - iTinggi)/2;
	CPen pen(PS_SOLID, 2, RGB(255, 0, 0));
	CPen* pOldPen;

	//
	// Create an outline
	//	
	pOldPen = dc->SelectObject(&pen);
	dc->Rectangle(iXPosisiPreview, iYPosisiPreview,iXPosisiPreview + iLebar + 2,
		iYPosisiPreview + iTinggi + 2);
	dc->SelectObject(pOldPen);

	//
	// Put in the box
	//
	dc->StretchBlt(iXPosisiPreview , iYPosisiPreview, iLebar, iTinggi,
		&memoriDC, 0, 0, rectMemory.Width(), rectMemory.Height(), SRCCOPY);
	
	//
	// Cleaning Up
	//
	fnt.DeleteObject();
	memoriDC.SelectObject(pOldBMP);
	memoriDC.DeleteDC();
	memBMP.DeleteObject();
	prnDC.Detach();

	//
	pWnd->ReleaseDC(dc);
}

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below. A list of licenses authors might use can be found here.


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralPrinting it Pin
Adeel Mirza3-Feb-10 20:29
Adeel Mirza3-Feb-10 20:29 
Generaldoesn't work under Vista SP1 Pin
Beiley10-May-08 9:44
Beiley10-May-08 9:44 
General[Message Removed] Pin
nompel4-Oct-08 2:18
nompel4-Oct-08 2:18 
GeneralRe: doesn't work under Vista SP1 Pin
CodeMasterX13-May-09 19:16
CodeMasterX13-May-09 19:16 
GeneralRe: doesn't work under Vista SP1 Pin
Beiley14-May-09 6:07
Beiley14-May-09 6:07 
Generalreading data from file when list control is very first shown Pin
Win32.sality10-Mar-08 22:43
Win32.sality10-Mar-08 22:43 
i have created the list view control that will have 9 entries if i click new button on the control and saves the structure in a file.
but when i click open from the menu i've created and select the filename only listview is displayed and gives error.
sombody suggest what to do...........
QuestionHow To Print listView items on A4 paper from VC++ Express Edition? Pin
chrisliando14-Nov-07 13:26
chrisliando14-Nov-07 13:26 
QuestionGetting Data from IP Camera using VC++ Pin
Kirubanandam6-Jan-06 22:54
Kirubanandam6-Jan-06 22:54 
Generalimprovement Pin
Franz Brunner8-Jan-03 22:48
Franz Brunner8-Jan-03 22:48 
GeneralGetDlgItem does take 1 argument, if ... Pin
Arnt Witteveen13-Apr-00 22:12
Arnt Witteveen13-Apr-00 22:12 
GeneralGetDlgItem does not take 1 argument Pin
Arnt Witteveen12-Apr-00 5:07
Arnt Witteveen12-Apr-00 5:07 
GeneralCWnd* pWnd defined twice Pin
Member 102010-Feb-00 7:29
Member 102010-Feb-00 7:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.