【问题标题】:Problem with Printing Content Of RichTextBox with Adorner Layers使用装饰层打印 RichTextBox 内容的问题
【发布时间】:2011-08-03 18:41:16
【问题描述】:

我正在尝试打印 RichTextBox 的内容,包括里面的装饰层。 我正在使用此代码进行打印

        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);
        }

我面临的问题是这段代码只打印屏幕上可见的内容,而不是编辑器的全部内容。

编辑 图片是装饰层,如果我使用上面的方法打印,它只打印屏幕上的可见部分而不是整个文档。

编辑

我正在尝试单独打印每一页,但在执行Editor.PageDown(); 之后我无法强制Editor.InvalidateVisual(); 有没有办法在我的方法中做到这一点?

【问题讨论】:

  • 你昨天不是才问这个吗?
  • @LarsTech 这涉及到一个不同的问题。
  • 你试过调用 xpsdw.Write(Editor.Document) 吗?
  • @AresAvatar 是的,它给出了一个错误“无法从 'System.Windows.Documents.FlowDocument' 转换为 'string'”
  • 是装饰者的问题,或者您没有获得由于滚动而看不到的内容。如果您需要打印在屏幕上阅读时必须滚动的“高”文档,那么您可能希望直接打印嵌入的流文档,而不是打印 RichTextBox。

标签: c# wpf printing richtextbox


【解决方案1】:

当控件在装饰层上绘制时,它们会向上搜索树,直到找到装饰层。通常这是一个窗口级别。在某些情况下,您需要一个更靠近控件或直接围绕控件的装饰层。在这种情况下,使用 <AdornerDecorator><RichTextBox /></AdornerDecorator> 包装控件

在您的情况下,您可能希望将装饰器的父元素或装饰器本身传递给打印逻辑。这样,打印逻辑将包含装饰层作为视觉的一部分。也许是这样的:

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

然后,将“EditorWrapper”传递给打印逻辑。

编辑

如果您只想打印 RichTextBox 的内容,那么您最好使用 FlowDocument 的内置分页功能。 FlowDocument 实现了 IDocumentPaginatorSource,它将返回一个可以打印文档的分页器。将该分页器传递给 XpsDocumentWriter,它应该会正确转储内容。

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

【讨论】:

  • 我这样做了&lt;AdornerDecorator&gt; &lt;RichTextBox Name="Editor" /&gt; &lt;/AdornerDecorator&gt; 并使用this 代码打印,但它没有工作
  • 如何将EditorWrapper 传递给打印逻辑? :s
  • 我也尝试了上面发布的代码并传递了xpsdw.Write(EditorWrapper);,但它只打印了屏幕上的可见内容。
  • 您能张贴您要打印的内容和实际打印的内容的屏幕截图吗?
  • 你不能这样做var src = doc as IDocumentPaginatorSource;它给出了Object reference not set to an instance of an object.
【解决方案2】:

我找到了这个代码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);
}

【讨论】:

  • 它不打印图像:(
  • 我使用了DataFormats.XamlPackage,但它没有打印装饰层
【解决方案3】:

装饰层是面向绘图的。所以剩下的一个选择是将整个 RichTextBox 转换为绘图并在 XPS 中将其打印为图像。

虽然这会带来多个问题...

  1. 它将打印富文本框占用或占用的外部和内部内容,即编辑器工具栏(如果它是富文本框的控件模板的一部分)、内部滚动条等。
  2. 如果有滚动条,则不会打印滚动条外的内容,因为图像将是文本框的精确“快照”(剩余文本被滚动条剪切)。

你会满意吗?

【讨论】:

  • 查看此内容以创建 WPF UI 控件(在您的情况下为 RichTextBox)的快照...mcleodsean.wordpress.com/2008/10/07/…
  • 这就是我在选项 2 中所说的...可能是您可以将高度和宽度增加到 100% 以获得快速实例(没有任何用户注意到更改的大小)并执行此快照调用(其中将包含所有内容)并将大小更改回原始大小!
  • 我可以这样做,但问题是如果我在richTextBox 中的内容比屏幕显示的多怎么办?
【解决方案4】:

我没有找到任何 100% 解决这个问题的方法,所以我试图将我的所有装饰层转换为实际图像。得到 100% 可行的解决方案后,我会更新问题。

【讨论】:

    猜你喜欢
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 1970-01-01
    • 2015-11-29
    • 1970-01-01
    相关资源
    最近更新 更多