简体   繁体   中英

Print FixedDocument with multiple FixedPage in pages per sheet in WPF

I have a very simple WPF application with only one button on it.

<Button x:Name="btnPrintCard" Grid.Row="2" HorizontalAlignment="Center" Content="Print Card" MinWidth="140" Foreground="White"
                Cursor="Hand" Background="#008080" Click="btnPrintCard_Click" />

I am trying to print multiple cards with size 3.370 x 2.125 on Typical A4 page. if arranged properly it should fit 10 cards per sheet from order left to right. Exactly like, adobe reader print command and setting custom page per sheet to 2 x 5.

Abode Reader打印设置

I am generating and printing card using below code:

private void btnPrintCard_Click(object sender, RoutedEventArgs e)
{
    try
    {
        PrintDialog printDialog = new PrintDialog();
        bool? pdResult = printDialog.ShowDialog();
        if (pdResult != null && pdResult.Value)
        {
            FixedDocument document = CreateFixedDocument();
            printDialog.PrintDocument(document.DocumentPaginator, "ID Card Printing");
        }
        MessageBox.Show("Printing done.");
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message + " :: " + ex.InnerException);
    }
}

private FixedDocument CreateFixedDocument()
{
    FixedDocument fixedDocument = new FixedDocument();
    // fixedDocument.DocumentPaginator.PageSize = new Size(96 * 3.370, 96 *2.125);
    fixedDocument.DocumentPaginator.PageSize = new Size(96 * 8.5, 96 * 11);

    for (int i = 0; i < 10; i++)
    {
        PageContent page = new PageContent();
        FixedPage fixedPage = CreateOneFixedPage();
        ((IAddChild)page).AddChild(fixedPage);
        fixedDocument.Pages.Add(page);
    }
    return fixedDocument;
}

private FixedPage CreateOneFixedPage()
{
    FixedPage page = new FixedPage();
    page.Background = Brushes.Red;
    page.Width = 96 * 3.370;
    page.Height = 96 * 2.125;

    TextBlock tbTitle = new TextBlock();
    tbTitle.Text = "xxx xxxxx Public School";
    tbTitle.FontSize = 24;
    tbTitle.Foreground = new SolidColorBrush(Colors.White);
    tbTitle.FontFamily = new FontFamily("Arial");
    FixedPage.SetLeft(tbTitle, 96 * 0.4); // left margin
    FixedPage.SetTop(tbTitle, 96 * 0.04); // top margin
    page.Children.Add((UIElement)tbTitle);

    Image image = new Image
    {
        Source = new BitmapImage(new Uri("http://www.ready-range.co.uk/_assets/images/products/BHSRR40R0R.jpg")),
        Height = 30,
        Width = 30
    };

    Border b = new Border();
    b.BorderThickness = new Thickness(1);
    b.BorderBrush = Brushes.Yellow;
    b.Child = image;

    FixedPage.SetLeft(b, 96 * 0.3);
    FixedPage.SetTop(b, 96 * 0.6); // top margin
    page.Children.Add((UIElement)b);

    //measure size of the layout
    Size sz = new Size(96 * 3.370, 96 * 2.125);
    page.Measure(sz);
    page.Arrange(new Rect(new Point(), sz));
    page.UpdateLayout();

    return page;
}

It result in printing successfully but with each card per page like this:

打印的图像

The problem is I want to print like above first image ie custom 2 by 5 per sheet.

Many Thanks.

This answer from another stackoverflow question helped a lot. I made some changes in order to get desire result which is adding my own method in the WpfPrint Class.

/// <summary>
/// Add fixed page to current fixed document
/// </summary>
/// <param name="card"></param>
/// <param name="flags"></param>
public void AddFixedPage(FixedPage card, ElementFlags flags)
{
    card.Measure(_infiniteSize);
    if (CurX > _fixedDocument.DocumentPaginator.PageSize.Width - MarginX)
    {
        CurY += card.DesiredSize.Height + MarginY;
        CurX = MarginX;
    }
    double extraCheck = 0;
    if ((flags & ElementFlags.BottomCheck2) == ElementFlags.BottomCheck2)
        extraCheck = card.DesiredSize.Height;
    if (CurY > _fixedDocument.DocumentPaginator.PageSize.Height - MarginY - extraCheck)
        StartPage();


    _curCanvas.Children.Add(card);
    card.SetValue(Canvas.LeftProperty, CurX);
    card.SetValue(Canvas.TopProperty, CurY);


    CurX += card.DesiredSize.Width + MarginX; //Added margin x for proper display             

    if (((flags & ElementFlags.NewLine) == ElementFlags.NewLine)  || CurX + card.DesiredSize.Width > _fixedDocument.DocumentPaginator.PageSize.Width) 
    {
        CurX = MarginX;
        CurY += card.DesiredSize.Height + MarginY;
    }
}

Now we can simply do this like this:

WpfPrint printer = new WpfPrint(new Size(96 * 9, 96 * 11));
printer.CurrentElementMargin = new Thickness(4);
printer.CurrentFontFamily = new FontFamily("Arial");
printer.MarginX = 20;
printer.MarginY = 10;

Now we can loop through every FixedPage:

 for (int i = 0; i < 10; i++)
    printer.AddFixedPage(CreateOneFixedPage(), WpfPrint.ElementFlags.BottomCheck2);

Finally, send print command like this:

PrintDialog printDialog = new PrintDialog();
bool? pdResult = printDialog.ShowDialog();
if (pdResult != null && pdResult.Value)                              
    printDialog.PrintDocument(printer.CurrentFixedDocument.DocumentPaginator, "Card Printing");

Thanks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM