6
votes

I'm printing a visual in WPF to a receipt printer (Star TSP 700II). When the visual is small it is fine and it prints okay.

However when the visual grows it will clip the image and it prints to a certain size on the roll in the Star printer and then it just cuts without printing the remainder of the image.

PrintDialog.PrintVisual(Grid1, "Test");

I've tried adjusting the PageMediaSize but that is not changing anything on the printout.

Interesting when I print to Microsoft XPS Document Writer the saved file has the full image.

enter image description here

I've also noticed the size it prints to is always maximum height = height of an A4 page. Question is how to I get it to print past the height of an A4 (when I print a test document from the printer preferences it is able to do this).

3
Your barcode is completely readable.AgentFire
Its only off a test server anyway, so doesn't really matter (thanks for the heads up though).DermFrench

3 Answers

9
votes

Ok I solved this using following class. Basically I put what I want to print inside a scrollviewer and put a stackpanel inside that, then pass this stackpanel to my print helper and it now prints without clipping:

public static class PrintHelper
{

    public static FixedDocument GetFixedDocument(FrameworkElement toPrint, PrintDialog printDialog)
    {
        var capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);
        var pageSize = new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight);
        var visibleSize = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
        var fixedDoc = new FixedDocument();
        //If the toPrint visual is not displayed on screen we neeed to measure and arrange it  
        toPrint.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
        toPrint.Arrange(new Rect(new Point(0, 0), toPrint.DesiredSize));
        //  
        var size = toPrint.DesiredSize;
        //Will assume for simplicity the control fits horizontally on the page  
        double yOffset = 0;
        while (yOffset < size.Height)
        {
            var vb = new VisualBrush(toPrint)
            {
                Stretch = Stretch.None,
                AlignmentX = AlignmentX.Left,
                AlignmentY = AlignmentY.Top,
                ViewboxUnits = BrushMappingMode.Absolute,
                TileMode = TileMode.None,
                Viewbox = new Rect(0, yOffset, visibleSize.Width, visibleSize.Height)
            };
            var pageContent = new PageContent();
            var page = new FixedPage();
            ((IAddChild)pageContent).AddChild(page);
            fixedDoc.Pages.Add(pageContent);
            page.Width = pageSize.Width;
            page.Height = pageSize.Height;
            var canvas = new Canvas();
            FixedPage.SetLeft(canvas, capabilities.PageImageableArea.OriginWidth);
            FixedPage.SetTop(canvas, capabilities.PageImageableArea.OriginHeight);
            canvas.Width = visibleSize.Width;
            canvas.Height = visibleSize.Height;
            canvas.Background = vb;
            page.Children.Add(canvas);
            yOffset += visibleSize.Height;
        }
        return fixedDoc;
    }

    public static void ShowPrintPreview(FixedDocument fixedDoc)
    {
        var wnd = new Window();
        var viewer = new DocumentViewer();
        viewer.Document = fixedDoc;
        wnd.Content = viewer;
        wnd.ShowDialog();
    }

    public static void PrintNoPreview(PrintDialog printDialog,FixedDocument fixedDoc)
    {
        printDialog.PrintDocument(fixedDoc.DocumentPaginator, "Test Print No Preview");

    }

}
1
votes

The last few days i also had this problem.

The solution was to render the root element in memory.

PrintDialog dlg = new PrintDialog();

// Let it meassure to the printer's default width
// and use an infinity height
Grid1.Meassure(new Size(dlg.PrintableAreaWidth, double.PositiveInfinity));

// Let it arrange to the meassured size
Grid1.Arrange(new Rect(Grid1.DesiredSize));

// Update the element
Grid1.UpdateLayout();

Then create a new papersize for the printer to use:

You should check your printer's cut settings (e.g use Receipt cutting mode).

// Create a new papersize with the printer's default width, and the Grids height
dlg.PrintTicket.PageMediaSize 
= new PageMediaSize(dlg.PrintableAreaWidth, Grid1.ActualHeight);

// Let's print !
dlg.PrintVisual(Grid1, "blah");

This works like a charm for me, and saved me lots of code.

As receipt printer's don't need pagination, I think this is very easy to use.

Note that I NOT use this method for rendering an UIElement created in XAML, it's all made in code with a StackPanel as root element.

1
votes

You are using PrintDialog.PrintVisual which is only supposed to print what you can see. For multi-page results you would need to do more.

You could try the DocumentPaginator http://msdn2.microsoft.com/en-us/library/system.windows.documents.documentpaginator.aspx

or

PrintDialog.PrintDocument http://msdn2.microsoft.com/en-us/library/system.windows.controls.printdialog.printdocument.aspx.