6

I am having a problem when using PrintDocument with margins.

No matter what I do there is always a margin around everything I print, this means that nothing is aligned where it needs to be.

Here is the code I am using to create the PrintDocument

public void Print()
{
   PrintDocument printDocument = new PrintDocument();
        printDocument.DefaultPageSettings.PaperSize = new PaperSize("A5",583,827);
        printDocument.OriginAtMargins = true;
        printDocument.DefaultPageSettings.Margins.Top = 0;
        printDocument.DefaultPageSettings.Margins.Left = 0;
        printDocument.DefaultPageSettings.Margins.Right = 0;
        printDocument.DefaultPageSettings.Margins.Bottom = 0;

        if (!string.IsNullOrWhiteSpace(PrinterName))
        {
            printDocument.PrinterSettings.PrinterName = PrinterName;
        }

        printDocument.PrintController = new StandardPrintController();
        printDocument.PrintPage += On_PrintPage;
        printDocument.Print();
}

The On_PrintPage method, has various calls to e.Graphics.Draw... methods.

How can I make it so that something I print at 0,0 will print in the very top left of the page. I know that if the printer cannot print that far to the edge of the page it will be blank, however it should do that rather than print 0,0 not in the top left of the page.

I'm really lost here

Nick Williams
  • 1,237
  • 6
  • 19
  • 40
  • There's more than one reason for paper margins. Sure, printers can't actually print inside the PageSettings.HardMargins, not much point in asking them to do so. But they also paper over mechanical issues, the path of the paper through the printer as well as it detecting the leading edge of the paper is not done with absolute accuracy. Very little you can do to fix that of course. Use an options window that allows the user to calibrate the offset, pass the values to e.Graphics.TranslateTransform() in your PrintPage event handler. – Hans Passant Jan 27 '14 at 16:09
  • Unfortunately I can't use any sort of options window, as the application prints notes out in bulk as triggered automatically by some event. The paper being printed onto is pre-printed with boxes that text must be inside of, these boxes are big enough as to accommodate any mechanical movement of the paper. But to ensure everything lines up 0,0 must be in the top left. Is there really no way to do this? Calling `TranslateTransform` would be fine but how could the transform amount/direction be determined so it will work with any printer? – Nick Williams Jan 27 '14 at 19:56

2 Answers2

2

interestingly the print function is too late to set most of the properties and would only apply to subsequent pages

you need to use PrintDocument.QueryPageSettings event instead and set the properties there and I always set the page settings not just defaults. then drawing at 0,0 should be as close as you can get (printer + driver allows)

  • I still coulnd't make it work. I'm drawing at 0,0, tried both `docToPrint.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);` and in `QueryPageSettings` event: ` e.PageSettings.Margins = new Margins(0, 0, 0, 0); ` still get the margins. – Jack Oct 21 '21 at 20:13
0

The OriginAtMargins property of the PrintDocument, when set to true, it will sets the origin of the provided Graphics object at the top-left corner of the margin. From the MSDN document Remarks section:

Calculating the area available to print requires knowing the physical size of the paper, the margins for the page, and the location of the Graphics object origin. When OriginAtMargins is true, the Graphics object location takes into account the PageSettings.Margins property value and the printable area of the page. When OriginAtMargins is false, only the printable area of the page is used to determine the location of the Graphics object origin, the PageSettings.Margins value is ignored.

Set it to false, to change it to the top-left corner of the printable area. If you need it to be at the top-left corner of the page, you will need to transform the graphics object to mach that coordinate; there isn't really a way to get around this:

void PrintDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
    var printArea = e.PageSettings.PrintableArea;

    e.Graphics.TranslateTransform(-printArea.X, -printArea.Y);

    // Build up the page here.
}

If you want to print landscape pages as well, this becomes tricky, as none of the properties of PageSettings are affected by this setting. This requires to know the angle the page is rotated by—as PrintableArea isn't always centered on the page—which can be acquired with PageSettings.PrinterSettings.LandscapeAngle. The value can only be either 90 or 270, and the code would look like this:

void PrintDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
    var printArea = e.PageSettings.PrintableArea;

    if (e.PageSettings.Landscape)
    {
        var pageSize = e.PageSettings.PageSize;

        switch (e.PageSettings.PrinterSettings.LandscapeAngle)
        {
            case 90:
                e.Graphics.TranslateTransform(
                    dx: -printArea.Y,
                    dy: -(pageSize.Width - (printArea.X + printArea.Width)));
                break;
            case 270:
                e.Graphics.TranslateTransform(
                    dx: -(pageSize.Height - (printArea.Y + printArea.Height)),
                    dy: -printArea.X);
                break;
        }
    }
    else
    {
        e.Graphics.TranslateTransform(-printArea.X, -printArea.Y);
    }

    // Build up the page here.
}

If you later want to use another transformation on a portion of the page, do not forget to use var gs = e.Save() before transforming and e.Restore(gs) to restore that transformation, instead of calling e.ResetTransform(), as the later will reset the transformation you did in the beginning.

Adam L. S.
  • 825
  • 1
  • 7
  • 14