Creating a Printing Class

Printing line-by-line without a Document/View framework

.

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:

  1. Include PrivatePrint.cpp and PrivatePrint.h into your project.
  2. Declare an object of CPrivatePrint.
  3. Call the member function Dialog() to let the user choose a printer and to initialize the object.
  4. 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.
  5. 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.
  6. Adjust the margins and the line spacing (dots between the print lines) with the member functions SetMargins() and SetDistance().
  7. 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.
  8. 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().
  9. Lines are printed with the function Print(). With lf(), blank lines are produced. Further functions are:
    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  
    All functions are explained in the remarks in the cpp file.
  10. 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 Kb
Download source - 10 Kb