Creating a Printing Class
Environment: tested on VC6 SP4 and VC7
Introduction
Do you still remember the times of the LINE printer (a dot-matrix printer)? Printing was still simple in these times. You simply sent print lines to the printer and lines in exactly this order were printed out. Searching for a way to use this technique, I created the class "CPrivatePrint". This class gives you the possibility to do exactly this and more.
This class works much like a old line printer. There is a "print-cursor" that moves downward with each printed line. It is as though you are printing on an endless strip of paper. The class ensures that the text is divided correctly on single sheets.
For example: You have to print a couple of lines of text in a desired font. With the CPrivatePrint class, you send lineprints. That's all. If you need to arrange the text on two or more pages, the class does it for you. You only have to set the desired margins. Therefore, the main function of the class is "print()", which sends the text line.
Although with this class line for line is printed, it is also possible to position the print cursor at any time and let it continue the printing at this position (use the SetHPos() function to do this).
You don't have to think about font handling. To use different fonts, you add the desired fonts with AddFontToEnvironment(). With SetActiveFont(), you switch between the fonts during the printing.
Some Features
- Printer selection is optional. (You can use the Windows printer selection dialog to select a printer or set a printer manually.)
- Supports header and footer lines.
- Supports bitmap printing.
- Supports up to 10 different fonts in one document.
- Supports font escapement.
- Used fonts can be printed in bold and/or big versions.
- For printer selection, you can use your own created dialog.
Using the Class
Here is the typical way to use the class:
- Include PrivatePrint.cpp and PrivatePrint.h into your project.
- Declare an object of CPrivatePrint.
- Call the member function Dialog() to let the user choose a printer and to initialize the object.
- Call the member function StartPrint(). This function MUST be called immediately after Dialog(), before other class functions are called. It creates the print document in the printer spooler. At the end of all printing, EndPrint() must be called to release it.
- Add the fonts that are needed with the member function AddFontToEnvironment(). Principally, it is enough to generate one font. The function returns a handle of the type HPRIVATEFONT, which then is needed for various other member functions. For each necessary font, the function must be called once. There are only 10 different fonts possible.
- Adjust the margins and the line spacing (dots between the print lines) with the member functions SetMargins() and SetDistance().
- If a header and/or a footer line is needed, the member function ActivateHF() must be called. See a description about this further down in this text.
- Call member function StartPage() to begin a new page. If the page ends, call EndPage(). Between these two functions, you place the line printings. Should it be necessary to print more lines than fit on one page (between the call of these two functions), the class ensures that EndPage() is called followed by a StartPage() automatically. A possibly necessary header and/or footer line is created automatically (if wanted). Normally, you use this function only once, at the start and the end. But if it is neccessary for your printing, you can create a new page every time by using EndPage() and StartPage().
- Lines are printed with the function Print(). With lf(), blank lines are produced. Further functions are:
All functions are explained in the remarks in the cpp file.Function Description SetFace() Adjusts the appearance of a font SetActiveFont() Changes the font SetEscapment() Changes the writing direction Line() Creates a line InsertBitmap() Inserts a bitmap ... and so forth - Call the member function EndPrint() to release the document in the spooler.
Some Words About Header/Footer Lines
If you need a header or a footer, or both, you have to create a callback function, such as this:
void HeaderFooter(CPrivatePrint*prt,int page,bool hf)
{
}
With CPrivatePrint::ActivateHF(), you say the class that has to call this callback function each time a header or footer line is neccessary. In the hf parameter, you get "true" if the header has to be written, and "false" if the footer has. The *prt pointer gives you a pointer to your CPrivatePrint-Object, which is calling the callback function.
If you are using a footer line, think that the bottom margin includes the height of the footer line. For example, if your footer needs 100 points of height, then your bottom margin should equal or be greater than 100.
Here is an example. It uses the class to print a selected text file. In the header of the printing, the name of the file is printed. In the footer, there is a page counter. Also, there is a bitmap logo in the footer. The example also shows the use of a header/footer line function:
void PrintText()
{
CPrivatePrint prt;
HPRIVATEFONT hFont;
FILE *f1;
CFileDialog dlg(TRUE,_T("txt"),NULL,OFN_HIDEREADONLY |
OFN_OVERWRITEPROMPT,"Text Files (*.txt)|
*.txt||");
char cBuffer[1024];
// get the file
if (dlg.DoModal() != IDOK) return;
g_strFileName = dlg.GetFileName();
// open the file
if ((f1 = fopen (g_strFileName,"r")) == NULL) {
AfxMessageBox (_T("can't open the file"));
return;
}
// initializing the class and printer selection
prt.Dialog();
// create the print document in the spooler
prt.StartPrint();
// Adding the arial font to the class
hFont = prt.AddFontToEnvironment("Arial");
// set margins and line spacing
prt.SetMargins(300,400,500,300);
prt.SetDistance(20);
// activate a header and footer line
prt.ActivateHF(HeaderFooter);
// now start a page
prt.StartPage();
// start printing the lines
while (fgets(cBuffer,1024,f1)) {
CUT_LF_AT_THE_END(cBuffer);
prt.Print(hFont,cBuffer,FORMAT_NORMAL);
}
// now end the page
prt.EndPage();
// close the print document and release it in the spooler
prt.EndPrint();
fclose (f1);
}
void HeaderFooter(CPrivatePrint*prt,int page,bool hf)
{
if (hf) // header line is wanted
{
prt->Print(prt->GetActiveFont(),g_strFileName,FORMAT_CENTER);
prt->lf(prt->GetActiveFont(),1);
}
else
{
CSize dim;
CRect margins;
CString strBuffer;
prt->GetDrawDimension(dim);
prt->GetMargins(margins);
prt->SetHPos(dim.cy-margins.bottom);
strBuffer.Format ("Seite %d",page);
prt->Print(prt->GetActiveFont(),strBuffer,FORMAT_CENTER);
prt->InsertBitmap(IDB_LOGO,FORMAT_RIGHT);
}
}
Downloads
Download demo project - 68 KbDownload source - 10 Kb

Comments
Centering bug fix
Posted by mschifter on 01/31/2007 10:04amHi, This is a timesaving class, but text was not centering for me on the page. I traced this down to line 367 in PrivatePrint.cpp. Change: lx += m_DimDraw.cx/2 - Size.cx/2; to: lx = m_DimDraw.cx/2 - Size.cx/2; and this should fix the problem.ReplySolution to one line per page problem....
Posted by aschon on 05/09/2006 04:28pmHow to control Font Size using this class
Posted by wuwei on 01/06/2005 12:37amHi, I want to print a text file using this class, but I want to print using different Font Size different rows. How to Realize it? Thanks.
ReplyHow to get the printer status
Posted by Namal on 10/21/2004 08:24amHi Guys, I wish to know how to get the printer status from an MFC application. I have tryed with querying the jobs for the printer and then get the status as follows if (!EnumJobs(hPrinter, 0, pPrinterInfo->cJobs, 2, (LPBYTE)pJobStorage, cByteNeeded, (LPDWORD)&cByteUsed, (LPDWORD)&nReturned)) { free(pPrinterInfo); free(pJobStorage); pJobStorage = NULL; pPrinterInfo = NULL; return FALSE; } But even when the printer is offline the status returned is always READY. If you have some idea of this please help me. Thank you.ReplyPrivatePrint is working in my developements
Posted by rgimilio on 03/09/2004 01:13pmI have incorporated PrivatePrint class in my MFC dialog based applications. It works. I have derived some private utilities for : - printing the content of a multiline edit control, - printing the content of a ListBox control Thanks for all.
ReplyHELP! works differently in debug than in release !!!
Posted by Legacy on 06/26/2003 12:00amOriginally posted by: sfraden
ReplyPlease help me for online printing
Posted by Legacy on 04/21/2003 12:00amOriginally posted by: azeem shaik
-------------------------------------------------
1.online printing: when ever user enter one Item information it should print imediately, the user complete the sales invoice then i have to call EndPage() function,so that i can cut the paper.
-------------------------------------------------
i want to print line by line,i have done this through ms-dos.
i want to do through MFC.
i want to print without calling EndPage() function.because EndPage() function is cutting paper(printer had autocutter). it is ending my task
--------------------------------------------------
ReplyUseing this code in Visual Basic 6.0
Posted by Legacy on 04/05/2003 12:00amOriginally posted by: Ritesh
Hi,
Could u tell me how could i use this code in vb6 and print a full length text file using this
Replythanks
How to add watermark option ot this
Posted by Legacy on 03/21/2003 12:00amOriginally posted by: satya
Hi i would liekt add the water mark option to the print dialog and also the optional caption for Watermarking hwo do i do that
Replyprinting list ctrl which variable column width with dialogbox
Posted by Legacy on 01/29/2003 12:00amOriginally posted by: praveen
hello sir
Replyi need to print listctrl which has variable number of columns and width of each column is variable.please help me
Loading, Please Wait ...