You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

WPF RichTextBox打印预览功能实现方案咨询

WPF RichTextBox 打印预览实现方案

我之前开发WPF文本编辑器时也踩过这个坑——RichTextBox自带的打印功能效果拉胯,而且原生没提供现成的打印预览控件,得自己动手搭。下面给你两个经过验证的可行方案,都是基于FlowDocument(RichTextBox的内容载体)来实现的:

方案一:自定义打印预览对话框(最灵活)

这个方案是自己做一个带DocumentViewer的窗口,把RichTextBox的内容克隆后放到预览控件里,同时集成打印功能,完全可控。

步骤1:创建预览窗口的XAML

新建一个Window(比如叫PrintPreviewWindow),布局很简单,核心就是DocumentViewer加操作按钮:

<Window x:Class="YourEditorNamespace.PrintPreviewWindow"
        Title="打印预览" Width="800" Height="600">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
            <Button x:Name="btnPrint" Content="打印" Width="80" Margin="0 0 10 0"
                    Click="BtnPrint_Click"/>
            <Button x:Name="btnClose" Content="关闭" Width="80" Click="BtnClose_Click"/>
        </StackPanel>
        <DocumentViewer x:Name="documentViewer"/>
    </DockPanel>
</Window>

步骤2:克隆RichTextBox的FlowDocument

直接用原RichTextBox的Document会导致预览时的操作同步到原编辑器,所以必须深克隆一份:

private FlowDocument CloneRichTextBoxDocument(RichTextBox rtb)
{
    // 通过Xaml序列化实现深拷贝,完整保留格式
    var stringWriter = new StringWriter();
    XamlWriter.Save(rtb.Document, stringWriter);
    var stringReader = new StringReader(stringWriter.ToString());
    return (FlowDocument)XamlReader.Load(stringReader);
}

步骤3:打开预览窗口并绑定内容

在主编辑器窗口的“打印预览”按钮点击事件里添加逻辑:

private void BtnPrintPreview_Click(object sender, RoutedEventArgs e)
{
    // 克隆文档,避免影响原编辑器内容
    var clonedDoc = CloneRichTextBoxDocument(yourRichTextBox);
    
    // 设置打印参数,确保预览和打印效果一致(以A4纸为例)
    clonedDoc.PageWidth = 8.5 * 96; // 96DPI下的A4宽度
    clonedDoc.PageHeight = 11 * 96; // 96DPI下的A4高度
    clonedDoc.PagePadding = new Thickness(96); // 1英寸边距
    
    // 打开预览窗口
    var previewWindow = new PrintPreviewWindow();
    previewWindow.documentViewer.Document = clonedDoc;
    previewWindow.ShowDialog();
}

步骤4:预览窗口的打印逻辑

PrintPreviewWindow的后台代码里实现打印和关闭功能:

private void BtnPrint_Click(object sender, RoutedEventArgs e)
{
    var printDialog = new PrintDialog();
    // 默认设置为A4纸
    printDialog.PrintTicket.PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOC4);
    
    if (printDialog.ShowDialog() == true)
    {
        documentViewer.PrintDocument(printDialog.PrintTicket);
    }
}

private void BtnClose_Click(object sender, RoutedEventArgs e)
{
    Close();
}

方案二:简化版——用PrintDialog结合临时FlowDocument

如果不需要单独的预览窗口,也可以直接借助PrintDialog的原生预览功能(部分系统支持):

private void BtnPrintWithPreview_Click(object sender, RoutedEventArgs e)
{
    var clonedDoc = CloneRichTextBoxDocument(yourRichTextBox);
    clonedDoc.PageWidth = 8.5 * 96;
    clonedDoc.PageHeight = 11 * 96;
    clonedDoc.PagePadding = new Thickness(96);
    
    var printDialog = new PrintDialog();
    // 绑定克隆后的文档到打印对话框
    printDialog.PrintDocument(((IDocumentPaginatorSource)clonedDoc).DocumentPaginator, "你的编辑器文档");
    
    // 弹出打印对话框,部分系统会显示预览选项
    if (printDialog.ShowDialog() == true)
    {
        printDialog.PrintDocument(((IDocumentPaginatorSource)clonedDoc).DocumentPaginator, "你的编辑器文档");
    }
}

关键注意事项

  • 必须克隆文档:直接引用原RichTextBox的Document会导致预览时的操作(比如滚动、选中文本)同步到原控件,深拷贝是必要的。
  • 统一DPI和纸张设置:FlowDocument的PageWidth/PageHeight要和打印纸张一致(用96DPI换算,WPF默认DPI为96),否则预览和打印格式会出现偏差。
  • 复杂格式兼容:Xaml序列化克隆的方式可以完整保留图片、表格等复杂元素的格式,比直接复制Blocks更可靠。

内容的提问来源于stack exchange,提问作者story sv

火山引擎 最新活动