Printing CRichEditCtrl

This tip comes from Rob Barnes
Thanks Rob! Here's the scoop directly from Rob:

What happens (in my app anyway) is that the user clicks a print button, and it gets the title of the document from another edit box in the dialog window (which that comes from a current record). It passes this to PrintRich, which just uses this as the title of the print job. PrintRich assumes the RichEditCtrl is a member of the class which it is called in, the member name is m_Rich.

In the PrintRich function, there are references to a CPrintAbortDlg class, just ignore it...it was an attempt at making a cancel dialog, but I was not sure about callback functions and how they work yet, but i left it in there anyway. I built this code from an SDK sample on msDevNet, I could not find anyhing like it on any web sites etc.

Thanks Rob!

Note: Rich Edit controls will only print truetype fonts in the proper size.
--- (bitmapped fonts will print extremely tiny on a printer, but OK on a screen)
void CSnippetDlg::OnPrint()
{
    CString Title;
    m_Title.GetWindowText(Title);
    this->PrintRich(Title);
}




BOOL CSnippetDlg::PrintRich(const CString& Title)
{
 CDC ThePrintDC; //create a device context to use
 CPrintDialog PrintDialog(FALSE);  //make a print dialog too

 if(PrintDialog.DoModal()==IDOK) //pressed the ok button on the print dialog?
    {
    ThePrintDC.Attach(PrintDialog.GetPrinterDC());//if so get settings
    }
 else
    return FALSE; //leave this procedure, before anything bad happens
 long CharRange=0;
 long LastChar=0;//will store document length
 DOCINFO di; //make a docinfo structure
 ::ZeroMemory(&di, sizeof(DOCINFO));
 di.cbSize=sizeof(DOCINFO);     //set size member
 di.lpszDocName=Title;//set doc name, was passed via another funtion
 FORMATRANGE fr;  //format range structure
 ::ZeroMemory(&fr, sizeof(FORMATRANGE));
 HDC hdc=ThePrintDC.GetSafeHdc();        //get handle to DC we are using
 fr.hdc=hdc;                                            //Set meber in FormatRange struct
 fr.hdcTarget=hdc;                //Set member in FormatRange struct
 //This bit here will get all the dimentions of the printer setup
 int nHorizRes = ThePrintDC.GetDeviceCaps(HORZRES),                 //width P in MM
 nVertRes = ThePrintDC.GetDeviceCaps(VERTRES),        //hight in raster lines
 nLogPixelsX = ThePrintDC.GetDeviceCaps(LOGPIXELSX),  //pixels per inch along x
 nLogPixelsY = ThePrintDC.GetDeviceCaps(LOGPIXELSY);  //pixels per inch along y
 //set the printable area of printer in the FormatRange struct
 fr.rcPage.left = 0; //these 2 mean top left
 fr.rcPage.top = 0;
 fr.rcPage.right    = (nHorizRes/nLogPixelsX) * 1440;//these 2 mean bottom right
 fr.rcPage.bottom   = (nVertRes/nLogPixelsY) * 1440;    //equation changes pixel to TWIPS
 // Set up some margins all around. Make them one inch
 //results vary on printers depending on setup
 fr.rc.left   = fr.rcPage.left + 1440;  // 1440 TWIPS = 1 inch.
 fr.rc.top    = fr.rcPage.top + 1440;
 fr.rc.right  = fr.rcPage.right - 1440;
 fr.rc.bottom = fr.rcPage.bottom - 1440;
 //select all text for printing
 CHARRANGE cr;
 cr.cpMin=0;
 cr.cpMax=-1;//-1 selects all
 fr.chrg=cr;//set this in FormatRange struct
 //get length of document, used for more than one page
 CharRange=m_Rich.GetTextLength();
 int ErrorStatus=0;
 //create cancel dialog
 CPrintAbortDialog* pAbort=new CPrintAbortDialog();
 pAbort->Create(IDD_ABORTPRINT, this);
 pAbort->ShowWindow(SW_SHOW);
 //Start Printing
 //ThePrintDC.SetAbortProc(&AbortProc(hdc, )); //dont know how callbacks works yet
 ThePrintDC.StartDoc(&di); //start printing document
 do
   {
   pAbort->Increment();//show it on print abort dialog
   ThePrintDC.StartPage(); //start the page
   LastChar = m_Rich.FormatRange( &fr, TRUE );//send text to DC, and record index
   //of last fitting char
   ErrorStatus=ThePrintDC.EndPage();//end this page, and record status
   cr.cpMin=LastChar;//Change charrange struct for next page
   cr.cpMax=CharRange; //using last char printed
   fr.chrg=cr;       //set that in formatrange struct
   }while(LastChar=0); //while there is stuff to print ot there
//is not an error(error is -No)
//if there is an error or printing has finished
//have to make sure AbortDoc is called instead of EndDoc if there has been a problem
  switch(ErrorStatus)
    {
    case SP_ERROR:
      {
      pAbort->DestroyWindow();
      delete pAbort;
      ThePrintDC.AbortDoc();
      AfxMessageBox("There was a general printing error, please check printer is working properly, connected, on line etc.", MB_OK | MB_ICONEXCLAMATION);
      return FALSE;
      }
    case SP_APPABORT:
      {
      pAbort->DestroyWindow();
      delete pAbort;
      ThePrintDC.AbortDoc();
      return FALSE;
      }
    case SP_USERABORT:
      {
      pAbort->DestroyWindow();
      delete pAbort;
      ThePrintDC.AbortDoc();
      return FALSE;
      }
    case SP_OUTOFDISK:
      {
      pAbort->DestroyWindow();
      delete pAbort;
      ThePrintDC.AbortDoc();
      AfxMessageBox("The print spooler is out of disk space, free up some disk space and try again.", MB_OK | MB_ICONEXCLAMATION);
      return FALSE;
      }
    case SP_OUTOFMEMORY:
      {
      pAbort->DestroyWindow();
      delete pAbort;
      ThePrintDC.AbortDoc();
      AfxMessageBox("Your computer is out of memory, shut down some applications and/or some windows and try again.", MB_OK | MB_ICONEXCLAMATION);
      return FALSE;
      }
    default:
      {
      pAbort->DestroyWindow();
      delete pAbort;
      ThePrintDC.EndDoc();
      return TRUE;
      }
    }
  }