Print Preview Demo

[Home]   [Puzzles & Projects]    [Delphi Techniques]   [Math Topics]   [Library]   [Utilities]

Search

 

Search DelphiForFun.org only

Support DFF

 If you benefit from the website,  in terms of knowledge, entertainment value, or something otherwise useful, consider making a donation via PayPal  to help defray the costs.  (No PayPal account necessary to donate via credit card.)  Transaction is secure.

 

If you shop at Amazon anyway,  consider using this link. We receive a few cents from each purchase.   Thanks.

In Association with Amazon.com

 

Contact

Feedback:  Send an e-mail with your comments about this program (or anything else).

 

Search DelphiForFun.org only

 

 

 

 

Here's a   "Print Preview" unit which will let you preview and print memo and stringlist data.   As usual, the motivation was the requirement to  preview and print these two component types in another program (the Crossword generator). 

The unit is based  on one among several found at programmer's heaven.com.  It was simple enough to get a handle on and flexible enough to let me add the missing StringGrid preview function.  The author is nearly anonymous  (no name just an invalid email address, rpetersn@usit.net).  So Ryan, if you ever run across this, drop me a line and I'll be glad to give you a better credit write-up.      

The unit handles multiple pages, scaling of the preview, and the ability to save preview pages and reload them at a later date.  There is much you can learn about metafiles and how they work by studying the code, but not too much that you must learn in order to to use it.      

Metafiles

The unit uses metafiles, one per page, as the ideal mechanism for accurate scaling of the same data to different devices.  A little about metafiles from Microsoft: 

"Enhanced metafiles provide true device independence. You can think of the picture stored in an enhanced metafile as a "snapshot" of the video display taken at a particular moment. This "snapshot" maintains its dimensions no matter where it appears on a printer, a plotter, the desktop, or in the client area of any application.

You can use enhanced metafiles to store a picture created by using the GDI functions (including new path and transformation functions). Because the enhanced metafile format is standardized, pictures that are stored in this format can be copied from one application to another; and, because the pictures are truly device independent, they are guaranteed to maintain their shape and proportion on any output device."

When a metafile is being built, data is written to a special "device context", a structure that defines the characteristics of a particular device.  Borland defines a TCanvas object type to represent a device context and a descendant TMetafileCanvas type to describe the special device context associated with metafiles.   Data is written to either type using the same TCanvas methods.  More significantly,  when a TMetafileCanvas is freed, the data written to it  is encoded in the associated metafile.  The metafile can then it can be saved and/or "played-back" to any specific device type using the "Stretchdraw" command for that device's canvas.  

Print Preview Methods

The main methods from the  PrintPreview unit are:

  • XInch and YInch convert a passed inch value to pixels using the current metafile resolution. 
  • MemoOut copies memo text (or any TStringlist object) to the metafile.  Parameters are
    •  aRect : the rectangle describing the area available for the drawing the text.
    • memolines: a stringlist containing the text lines to be displayed.
    • memofont: the font to be used for displaying the text.
    • LastCharDisplayed:  If the data cannot all be displayed in the rectangle provided, this is the position of the last character that was displayed.
    • Returnremainder: A Boolean value indicating whether the input stringlist should have the displayed characters removed.  If true and the list is not empty, the text remaining needs to be displayed in the next column, page, etc. 
  • StringGridOut write a StringGrid to the MetafileCanvas.  The procedure will check if an OnDrawCell exit is defined for the StringGrid.  If so, a special protocol is used to call the exit.  In a normal DrawCell exit, the passed StringGrid address is used both to provide access to the data and canvas for drawing. In this case the two required address are different  - the grid for data information and the MetafileCanvas for the drawing location.  I solve this be passing the two addresses in a TList to the OnDrawCell exit.  The exit can recognize this case and handle it appropriately.   You can check the demo program for details. 

     Parameters: 

    • Grid : The Stringgrid to draw
    •  NewWidth The width of the image on the MetafileCanvas.
    • Origin:  The X, Y coordinates of the top left corner of the grid.
    • Showgrid a Boolean value indicating that the interior gridlines of the Stringgrid are to be drawn  
    • Showdata A Boolean value indicating that the data in the Stringgrid cells is to be drawn.
    • NewHeight  An output of StringGridOut indicating the height of the drawn Stringgrid.
  • GetGridHeight  This function returns the height of the passed StringGrid before it is drawn.  This allows us to move to a new page if necessary before actually rendering the grid.  

    Parameters are:

    • Grid : The Stringgrid to draw
    •  NewWidth The width of the image on the MetafileCanvas.
  • NewJob: Starts a  new job.
  • NewPage Start a new page.
  • PageCount  Number of pages created for this job so far.
  • Currentpage The page currently being built or displayed.
  • PageSize The total width and height of a page 
  • PrintSize : The height and width of the printable area of the page.
  • DisplayPage(Page : Integer);
  • Preview: Setup and display page 1.  
  • PrintPage:
    • PageNum : The page number to print.
  • PrintAll: Print all pages.
  • SaveToFile:  Save the metafiles (one per page) to a single disk file.
    •   FileName: The file name to save to. 
    •  Note that even though files are EMF format internally, the disk file created is not in standard EMF file format.   There is one file for each preview page but  I write a file stream saving all of the pages (metafiles) in a single disk file. 
  • LoadFromFile: Load previously saved metafiles.   
    • Filename : The file name to load from.

The Demo Program

The string grid in the demo  illustrates use of an OnDrawCell exit to display any cell with a valid numeric value in red and underlined. (The grid is initially filled with random numbers and letters. You can double click on any white cell to modify the data.)

On page 1 of the output, the demo will preview or print the StringGrid followed by the introduction memo.  Page 2 has the order reversed and prints the memo in narrow format to force some page breaks.  It will probably result in 4 pages for most devices.

Addendum June 10, 2007:  Version 2 posted today adds the ability to automatically insert a page break when it reaches the end of a page.    Fixed rows (column headers) are replicated at the top of each continues page.   The fixed cells are now colored using the grid's FixedColor property.  

I'll leave the download zip file link for the executable file in the links below because I put it there in 2004.  But there's not much reason to download that I can think of.   

Addendum January 23, 2008:  A recent question from a viewer about right aligned text triggered a restudy of the Margin setting code added last year.  A new button in the demo program prints a message in each corner of the page based on margin values set.    New procedures SetInchMargin and SetPixelMargin make it easy to set margins for each border.   Note for programmers - this change has replaced TSpinEdit controls with TDFFSpinEdit controls to  achieve compatibility with Turbo Delphi Explorer, a free updated Delphi version which does not include TSpinEdit.

Download and Explore Programs

Click to download source code for Print Preview and the demo program. 

Click to download executable demo program.

Future Explorations

  • The unit  calls the Printer.BeginDoc procedure while building each new page - this is somewhat awkward and would be unnecessary except that  some printer characteristics are used even in scaling the  screen preview.   I think that printer characteristics could be collected at NewJob time and  "BeginDoc"s not issued until actual playback to the printer is taking place. 
  • I'm suspicious of the methods used to get and set font, pen, and  brush in the metafiles.  They are simply "set" with the equals operator.  I think that assigning the controls would be the proper way to do it.     


 

  [Feedback]   [Newsletters (subscribe/view)] [About me]
Copyright © 2000-2009, Gary Darby    All rights reserved.