Print at full scale in C#

[Print at full scale]

This example shows how you can print at full scale so objects drawn on the screen are the same size when printed. Note that your screen and printer are probably not calibrated exactly so the result will not match perfectly. It should be fairly close, however.

The example Draw and move line segments in C# shows how you can draw and move lines on the screen. This example is similar except it adds a File menu with Print Preview and Print commands.

This example manages its line segments in the same was as the previous example. It does make one change to the drawing code, however. Rather than making the Paint event handler draw the lines directly, this version moves the drawing code into a new DrawLines method> The following code shows the idea.

// Draw the lines.
private void picCanvas_Paint(object sender, PaintEventArgs e)
{
    DrawLines(e.Graphics);
}

// Draw the lines.
private void DrawLines(Graphics gr)
{
    ...
}

Now the program can use the same drawing method to provide a print preview or print.

The really interesting part of the program is the following PrintPage event handler, which generates printing commands for a preview or print out.

// Print the lines.
private void pdocLines_PrintPage(object sender, PrintPageEventArgs e)
{
    // Get the screen's resolution.
    float dpix, dpiy;
    using (Graphics gr = this.CreateGraphics())
    {
        dpix = gr.DpiX;
        dpiy = gr.DpiY;
    }

    // Make the page scale from printer
    // resolution to hundredths of inches.
    e.Graphics.ScaleTransform(100f / dpix, 100f / dpiy);

    // Draw the lines on the page.
    DrawLines(e.Graphics);

    // We're done.
    e.HasMorePages = false;
}

Normally screen coordinates are measured in pixels but printer coordinates are measured in hundredths of inches. To print at the correct scale, the program must convert from screen coordinates to printer coordinates.

To do that, it first creates a new Graphics object on the screen. Because the for (this) is on the screen, its CreateGraphics method returns an object representing the screen. The code then uses that object’s DpiX and DpiY properties to get the number of dots (pixels) per inch on the screen. (This is typically 96 dots per inch.)

Next the code gives the printing Graphics object a scale transformation to convert from dots on the screen to hundredths of inches. For example, the scale factor in the X direction divides by dpix to convert from dots (pixels) to inches. Then multiplying by 100 converts from inches to hundredths of inches.

After it sets the Graphics object’s scale transformation, the code simply calls DrawLines as before and the printout is drawn at a scale that matches the screen.

Note that the scale transformation applies to line thicknesses, too. The example uses stock pens such as Pens.Blue and Pens.Black to draw its lines. The stock pens have thickness 1 so when they are printed the lines have thickness approximately 1/96th of an inch thick.

If you draw the lines with thickness 0, that tells the GDI+ drawing system to draw the lines as thinly as possible. On the printer, that will probably produce a very thin line.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in drawing, GDI+, graphics, printing and tagged , , , , , , , , , , , , , , , , . Bookmark the permalink.

2 Responses to Print at full scale in C#

  1. John says:

    Hi Rod,
    I have tried to draw a rectangle at a certain size(20mm x 80mm) with
    gr.DrawRectangle(new Pen(Brushes.Red, 0.5f), 20,20, 20, 80);
    in Drawlines and
    e.Graphics.ScaleTransform(100f / dpix, 100f / dpiy);
    in printpage but it comes out wrong size but if i delete
    e.Graphics.ScaleTransform(100f / dpix, 100f / dpiy);
    and use
    gr.PageUnit = GraphicsUnit.Millimeter;
    in drawlines it is the right size, but it seems to mess up the mouse location x,y. is there anyway of rectifying this so i can use the rectangle.contains accurately.

    sorry for not explaining properly, i am not a very good programmer.
    Thank you

    • RodStephens says:

      This example draws in inches not millimeters. Try using this:

      e.Graphics.ScaleTransform(25.4f / dpix, 25.4f / dpiy);

      That should convert screen units into millimeters.

Leave a Reply

Your email address will not be published. Required fields are marked *