WPF - Imprimindo com FlowDocument


Se você precisa imprimir em uma aplicação WPF vai ter que mudar a sua forma de pensar sobre a impressão se você costumava usar a impressão em aplicações usando o GDI ou GDI+.(O WPF possui mais recursos de impressão que o Windows Forms.)

Para imprimir com WPF você pode usar o objeto FlowDocument, incluir nesse objeto o conteúdo que você deseja imprimir e enviar para a impressora. Ou seja o FlowDocument é a classe que podemos usar para armazenar e formatar o texto que desejamos imprimir. Parece simples não é mesmo ?

Mas o que vem a ser esse tal de FlowDocument (Documentos de Fluxo)?

Os documentos de fluxo permitem aos desenvolvedores criar documentos de forma nativa no WPF.

Os documentos de fluxo definem os fluxos de texto de uma forma que lembra os documentos HTML, mas possuem mais recursos e oferecem um número maior de opções de layout avançadas. Eles são normalmente definidos em XAML (Extensible Application Markup Language), a linguagem de marcação padrão baseada em XML.

Abaixo temos um exemplo de código XAML que instancia uma classe FlowDocument e uma classe Paragraph (com texto) onde o parágrafo é adicionado à coleção de blocos de FlowDocument.

<FlowDocument>
  <Paragraph>Usando FlowDocument</Paragraph>
</FlowDocument>

Obs: O mesmo resultado poderia ser obtido via código da seguinte forma:

Dim doc as new FlowDocument()
Dim parag as new Paragraph()

para.Inlines.Add(“Usando FlowDocument”)
doc.Blocks.Add(para)

De forma básica os documentos de fluxo são coleções de blocos. Internamente, todos os blocos são classes do WPF que derivam da classe System.Windows.Documents.Block.

Uma lista dos tipos de blocos mais importantes é a seguinte:

Bloco Descrição
Paragraph Contém texto (formatado de maneira mais avançada).
List Contém listas de vários tipos (numeradas, com marcadores etc.).
Table Contém tabelas similares às do Microsoft Word ou do HTML.
BlockUIContainer Contém vários elementos de interface do usuário que fazem parte do fluxo geral.
Section Contém um grupo de outros blocos. As seções são úteis para a aplicação de atributos comuns a um grupo de blocos, como os mesmos atributos de fonte a vários parágrafos.

A impressão em WPF usando o FlowDocument exige que você defina os seguintes namespaces no seu projeto:

using System.Printing;
using System.Windows.Documents;
imports System.Printing
imports System.Windows.Documents
C# VB .NET

O namespace System.Windows.Document também é usado mas ele já é incluído no seu projeto quando você criar uma novo projeto WPF.

O processo de impressão usando o FlowDocument em WPF envolve as seguintes etapas:

// Cria um objeto PrintDialog
PrintDialog printDlg = new PrintDialog();
// Cria um objeto PrintDialog
Dim printDlg as new PrintDialog()
C# VB. NET

O objeto FlowDocument é usado para criar um FlowDocument que possui itens como parágrafo, linha, imagem, etc.

// Cria um FlowDocument
FlowDocument doc = new FlowDocument(new Paragraph(new Run("Texto incluido no flowdocument")));
doc.Name = "FlowDoc";
C#
'Cria um FlowDocument
Dim doc As New FlowDocument(New Paragraph(New Run("Texto incluido no flowdocument")))
doc.Name = "FlowDoc"
VB .NET

Você deverá criar um objeto IDocumentPaginatorSource a partir do FlowDocument ;

// Cria um IDocumentPaginatorSource a
partir de um FlowDocument
IDocumentPaginatorSource idpSource = doc;
// Cria um IDocumentPaginatorSource a
partir de um FlowDocument
Dim idpSource As IDocumentPaginatorSource = doc
C# VB .NET

O último passo é invocar o método PrintDialog.PrintDocument para chamar a janela de diálogo de impressão que irá permitir selecionar uma impressora e enviar o documento para a impressão. O método PrintDocument usa um objeto DocumentPaginator que você pode obter a partir da propriedade IDocumentPaginatorSource.DocumentPaginator conforme exibida no código a seguir:

// Chamar o método PrintDocument para enviar o documento para a impressora
printDlg.PrintDocument(idpSource.DocumentPaginator, "Imprimindo com WPF.");
C#
' Chamar o método PrintDocument para enviar o documento para a impressora
printDlg.PrintDocument(idpSource.DocumentPaginator, "Imprimindo com WPF.")
VB .NET

Vejamos agora um exemplo básico de impressão de um texto usando o FlowDocument.

Imprimindo com FlowDocument

Crie um novo projeto do tipo WPF Application usando o Visual Basic 2008 Express Edition com o nome printFlowDocumentWPF;

A seguir no arquivo window1.xaml criado inclua o código abaixo que irá criar um Button e definir o seu evento Click;

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="imprimir com WPF" Height="216" Width="385">
    <Grid Height="146" Width="352">
        <Button Content="impressão de texto simples em WPF com FlowDocument" Height="30" Margin="22,21,25,0"
                Name="prntTexto" VerticalAlignment="Top" Click="prntTexto_Click" />
    </Grid>
</Window>

No arquivo code-behind window1.xaml.vb vamos definir o código do evento Click do controle Button:

 Private Sub prntTexto_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        ' Cria um PrintDialog
        Dim printDlg As New PrintDialog()
        ' Cria um FlowDocument
        Dim doc As FlowDocument = CriaFlowDocument()
        doc.Name = "FlowDoc"

        ' Cria um IDocumentPaginatorSource a partir do FlowDocument
        Dim idpSource As IDocumentPaginatorSource = doc
        ' Chama o método PrintDocument para envair o documento para a impressoa
        printDlg.PrintDocument(idpSource.DocumentPaginator, "Imprimindo com WPF.")
    End Sub

Precisamos também definir o método CriaFlowDocument() que retorna um FlowDocument conforme o código a seguir:

Private Function CriaFlowDocument() As FlowDocument
        ' Cria um  FlowDocument
        Dim doc As New FlowDocument()
        ' Cria uma Section
        Dim sec As New Section()
        ' Cria um Parágrafo
        Dim p1 As New Paragraph()
        ' Cria e adiciona negrito, italico e underline
        Dim bld As New Bold()
        bld.Inlines.Add(New Run("Primeiro Parágrafo"))
        Dim italicBld As New Italic()
        italicBld.Inlines.Add(bld)
        Dim underlineItalicBld As New Underline()
        underlineItalicBld.Inlines.Add(italicBld)

        ' adiciona negrito, italico e underline ao parágrafo
        p1.Inlines.Add(underlineItalicBld)
        ' Adiciona o parágrafo a Section
        sec.Blocks.Add(p1)
        ' Inclui a Section no FlowDocument
        doc.Blocks.Add(sec)

        Return doc
    End Function

Com isso será impresso a linha : Primeiro Parágrafo em negrito, itálico e sublinhado.

Uma outra forma de imprimir usando este recurso é definir uma rotina para impressão conforme abaixo:

 Private Sub PrintComDocumentCondensed(ByVal text As String,  Optional ByVal printCaption As String = "")

        'Cria um documento passando um novo parágrafo e texto
        Dim doc As New FlowDocument(New Paragraph(New Run(text)))
        doc.PagePadding = New Thickness(100) 'Cria margens no texto

        Dim diag As New PrintDialog()

        'Envia o documento para a impressora
        diag.PrintDocument( _
            CType(doc, IDocumentPaginatorSource).DocumentPaginator, _
            printCaption)
    End Sub

Para imprimir basta chamar a rotina passando os parâmetros:

PrintComDocumentCondensed("Imprima este texto", "Minha impressão com o WPF")

Visualizando documentos de Fluxo

De forma padrão os documentos de fluxo são processados por meio de um controle FlowDocumentReader, que oferece um conjunto de recursos padrão como zoom, paginação, diversos modos de exibição e um recurso de pesquisa. (Os documentos de fluxo precisam ser hospedados por algum tipo de controle capaz de exibi-los. )

O visualizador padrão para documentos de fluxo é o controle FlowDocumentReader, que é instanciado automaticamente, a menos que você utilize um controle diferente de forma explícita.

O WPF oferece três controles diferentes para a exibição de documentos de fluxo:

Veja o artigo : WPF - Exibindo um arquivo texto no FlowDocumentReader onde um mostro um exemplo de como usar o FlowDocumentReader;

Pegue o projeto completo aqui: printFlowDocumentWPF.zip

Eu sei é apenas C# , mas eu gosto...

Referências:


José Carlos Macoratti