开发者

Problem with Printing Content Of RichTextBox with Adorner Layers

开发者 https://www.devze.com 2023-03-25 12:06 出处:网络
I am trying to print the content of RichTextBox including the Adorner Layers inside. I am using this code to print

I am trying to print the content of RichTextBox including the Adorner Layers inside. I am using this code to print

        double w = Editor.ExtentWidth;  // Editor is the RichTextBox
        double h = Editor.ExtentHeight;

        LocalPrintServer ps = new LocalPrintServer();
        PrintQueue pq = ps.DefaultPrintQueue;
        XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(pq);
        PrintTicket pt = pq.UserPrintTicket;
        if (xpsdw != null)
        {
            pt.PageOrientation = PageOrientation.Portrait;
            PageMediaSize pageMediaSize = new PageMediaSize(w, h);
            pt.PageMediaSize = pageMediaSize;

            xpsdw.Write(Editor);
        }

The problem I'm facing is that this code only prints the content that is visible on the screen, not the whole content of the Edi开发者_Go百科tor.

EDIT The pictures are adorner layers, If I print using the method above, it only prints the visible part on the screen not the whole document.

Problem with Printing Content Of RichTextBox with Adorner Layers

Edit

I'm trying to print each page separately but I cant force Editor.InvalidateVisual(); after doing a Editor.PageDown(); Is there a way I can do that in my method ?


When controls draw on the adorner layer, they search up the tree until they find an adorner layer. Often times this is a the window level. In some cases, you'll want an adorner layer closer to the control, or directly around the control. In this case, wrap the control with an <AdornerDecorator><RichTextBox /></AdornerDecorator>

In your case, you'd probably want to pass a parent element of adorner decorator, or the decorator itself to the print logic. This way the print logic would include the adorner layer as part of the visual. Maybe something like this:

<Grid Name="EditorWrapper">
   <AdornerDecorator>
      <RichTextBox />
   </AdornerDecorator>
</Grid>

Then, pass "EditorWrapper" to the print logic.

EDIT

If you just want to print the contents of the RichTextBox, then you might be best to use the built-in pagination capabilities of the FlowDocument. FlowDocument implements IDocumentPaginatorSource, which will return a paginator that can print the document. Pass that paginator to the XpsDocumentWriter and it should dump the content properly.

var doc = Editor.Document;
var src = doc as IDocumentPaginatorSource;
var pag = src.DocumentPaginator;
xpsdw.Write(pag);


I found this code here:

// Serialize RichTextBox content into a stream in Xaml or XamlPackage format. (Note: XamlPackage format isn't supported in partial trust.)
TextRange sourceDocument = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
MemoryStream stream = new MemoryStream();
sourceDocument.Save(stream, DataFormats.Xaml);

// Clone the source document's content into a new FlowDocument.
FlowDocument flowDocumentCopy = new FlowDocument();
TextRange copyDocumentRange = new TextRange(flowDocumentCopy.ContentStart, flowDocumentCopy.ContentEnd);
copyDocumentRange.Load(stream, DataFormats.Xaml);

// Create a XpsDocumentWriter object, open a Windows common print dialog.
// This methods returns a ref parameter that represents information about the dimensions of the printer media.
PrintDocumentImageableArea ia = null;
XpsDocumentWriter docWriter = PrintQueue.CreateXpsDocumentWriter(ref ia);

if (docWriter != null && ia != null)
{
    DocumentPaginator paginator = ((IDocumentPaginatorSource)flowDocumentCopy).DocumentPaginator;

    // Change the PageSize and PagePadding for the document to match the CanvasSize for the printer device.
    paginator.PageSize = new Size(ia.MediaSizeWidth, ia.MediaSizeHeight);
    Thickness pagePadding = flowDocumentCopy.PagePadding;
    flowDocumentCopy.PagePadding = new Thickness(
            Math.Max(ia.OriginWidth, pagePadding.Left),
            Math.Max(ia.OriginHeight, pagePadding.Top),
            Math.Max(ia.MediaSizeWidth - (ia.OriginWidth + ia.ExtentWidth), pagePadding.Right),
            Math.Max(ia.MediaSizeHeight - (ia.OriginHeight + ia.ExtentHeight), pagePadding.Bottom));
    flowDocumentCopy.ColumnWidth = double.PositiveInfinity;

    // Send DocumentPaginator to the printer.
    docWriter.Write(paginator);
}


Adorner layers are are drawing oriented. So one option left is to convert the entire RichTextBox into a drawing and print that as an Image in XPS.

Although this poses multiple issues...

  1. It will print the external and internal contents that occupy or occupied by the richtextbox i.e. editor toolbar (if it is part of the control template of the rich text box), internal scroll bars etc.
  2. If there are scrollbars then the content out of the scrollbars are not going to be printed as the image will be the exact "snapshot" of the textbox (with remaining text clipped by srollbars).

Will you be happy with that?


I didn't find any way that works 100% for this problem, so I'm trying to transform all my adorner layers to actual images. I'll update the question once I get a 100% working solution.

0

精彩评论

暂无评论...
验证码 换一张
取 消