Visual Basic .NET - Imprimindo com PrintDocument
Já estamos usando na versão do VB .NET 2008 e a impressão no Visual Basic ainda é um tema que gera muitas discussões e dúvidas. Afinal , apesar de todos os esforços não temos ainda uma ferramenta nativa no Visual Basic para impressão que atenda as necessidades diárias de um desenvolvedor que usa a linguagem. Geralmente somos forçados a recorrer a componentes de terceiros , e , aos custos que isso acarreta.
Para saber mais sobre esse assunto veja os meus artigos já publicados:
Neste artigo eu vou procurar complementar as informações já publicadas aplicadas ao Visual Basic 2008 (estou usando a versão Express).
Já sabemos que a classe PrintDocument é o coração do processo de impressão no Visual Basic e ao usá-la em seu programa será criada uma instância desta classe com os eventos que serão usados para a impressão.
O objeto PrintDocument dispara quatro eventos chaves básicos:
Depois que você criou um objeto PrintDocument e definiu os manipuladores de eventos você pode fazer 3 coisas com ele:
Nota: O controle PrintPreviewControl exibe uma janela de visualização da impressão com a diferença que ele fica no seu formulário e não apresenta os mesmos botões do PrintPreviewDialog mas possui métodos que permitem simular o mesmo comportamento.
Vejamos a aplicação destes recursos em um exemplo no Visual Basic 2008 Express Edition.
Abra o VB 2008 Express Edition (você pode usar o VS 2008) e crie um novo projeto do tipo Windows Application com o nome imprimindoNet;
Defina no formulário três botões de comando - Button1, Button2 e Button3 - no formulário form1.vb e, a partir da ToolBox, inclua os componentes: PrintDocument, PrintPreviewDialog e PrintDialog conforme abaixo:
Agora defina o namespace para impressão:
Imports
System.Drawing.PrintingDefina também o objeto PrintDocument usando a palavra-chave WithEvents de forma a capturar mais facilmente os eventos do objeto;
Private
WithEvents m_PrintDocument As PrintDocumentAgora inclua o código abaixo em cada um dos eventos Click dos botões de comando:( A direita temos o resultado para os botões de visualização)
'imprimir direto
Private
Sub Button1_Click(ByVal
sender As
System.Object, ByVal
e As System.EventArgs)
_ Handles Button1.Click m_PrintDocument = New PrintDocument m_PrintDocument.Print() End Sub
|
|
'criar visualizacao da impressao Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _Handles Button2.Click
m_PrintDocument =
New
PrintDocument PrintPreviewDialog1.Text = "Usando - PrintPreviewDialog" PrintPreviewDialog1.Document = m_PrintDocument PrintPreviewDialog1.ShowDialog() End Sub
|
|
'criar dialogo de impressao Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _Handles Button3.Click
m_PrintDocument =
New
PrintDocument PrintDialog1.Document = m_PrintDocument PrintDialog1.ShowDialog() End Sub |
Só falta definir uma rotina para imprimir algo no evento PrintPage;
'gerar a pagina e imprimir Private Sub m_PrintDocument_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles m_PrintDocument.PrintPage
e.Graphics.DrawRectangle(caneta, e.MarginBounds) caneta.DashStyle = Drawing2D.DashStyle.Dash caneta.Alignment = Drawing2D.PenAlignment.Outset e.Graphics.DrawRectangle(caneta, e.PageBounds) End Using '¡ndica que nao ha mais paginas a serem impressas e.HasMorePages = False End Sub
|
E pronto, temos uma visão de como tratar os objetos para impressão de forma básica.
Vamos agora então mostrar algo mais prático. Vamos criar uma rotina para imprimir o conteúdo de uma tabela a partir de um formulário em uma aplicação Windows.
Vamos criar um banco de dados no Microsoft Access chamado Teste.mdb e uma tabela chamada Clientes com os seguintes campos:
Inclua também alguns dados na tabela para efetuar os testes.
Abra o Visual Basic 2008 Express Edition e crie um novo projeto do tipo Windows Froms Application com o nome de impressaoTeste;
A seguir crie um novo DataSource na opção Data -> Add New DataSource;
Selecione o objeto DataBase e defina a conexão com o banco de dados Teste.mdb;
Selecione a tabela Clientes e clique no botão FInish;
Agora selecione o formulário form1.vb e abra a janela Data Sources. Defina o modo DataGridView para o mesmo e arraste e solte-o no formulário. Será criado um DataGridView e toda a estrutura para manutenção dos dados. Inclua também um componente PrintDocument a partir da ToolBox;
Inclua na barra de navegação do BindingNavigator um novo ícone para a impressão dos dados:
Agora vamos usar o evento Click relacionado ao ícone para imprimir os dados da tabela Clientes.
Primeiro defina os namespaces usados no projeto:
Imports
System.DataImports
System.Data.OleDbImports
System.Drawing.PrintingA seguir defina as variáveis usadas :
Dim
cmd As OleDbCommandPrivate paginaAtual As Integer = 1
Private MyConnection As OleDbConnection
Private Leitor As OleDbDataReader
Private RelatorioTitulo As String
Agora vamos ao código...
No evento Click do ToolStripButton devemos incluir o seguinte código que será responsável pela definição dos objetos e eventos de impressão:
Private Sub ToolStripButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton1.Click'obtem a string de conexao MyConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\teste\Teste.mdb")
RelatorioTitulo = "Lista de Clientes - "'define os objetos printdocument e os eventos associados Dim pd As Printing.PrintDocument = New Printing.PrintDocument()
'IMPORTANTE - definimos 3 eventos para tratar a impressão : PringPage, BeginPrint e EndPrint. AddHandler pd.PrintPage, New Printing.PrintPageEventHandler(AddressOf Me.pdRelatorios_PrintPage) AddHandler pd.BeginPrint, New Printing.PrintEventHandler(AddressOf Me.Begin_Print) AddHandler pd.EndPrint, New Printing.PrintEventHandler(AddressOf Me.End_Print)
'define o formulário como maximizado e com Zoom With objPrintPreview.Document = pd .WindowState = FormWindowState.Maximized .PrintPreviewControl.Zoom = 1 .Text = "Relacao de Clientes".ShowDialog() End With Catch ex As ExceptionMessageBox.Show(ex.ToString()) End Try End Sub |
No evento Begin_Print vamos abrir o DataReader com os dados da tabela Clientes;
'A conexÆo e o DataReader ‚ aberto aqui Private Sub Begin_Print(ByVal sender As Object, ByVal e As Printing.PrintEventArgs)
Leitor = MyComand.ExecuteReader() paginaAtual = 1
|
Agora temos a rotina mais trabalhosa, onde iremos definir o leiaute da página, a fonte, as margens, os campos a serem impressos e a imagem a ser impressa;
'Layout da(s) p gina(s) a imprimir Private Sub pdRelatorios_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)'Variaveis das linhas Dim LinhasPorPagina As Single = 0Dim PosicaoDaLinha As Single = 0 Dim LinhaAtual As Integer = 0
Dim MargemSuperior As Single = e.MarginBounds.Top + 100 Dim MargemDireita As Single = e.MarginBounds.Right Dim MargemInferior As Single = e.MarginBounds.Bottom Dim CanetaDaImpressora As Pen = New Pen(Color.Black, 1) Dim codigo As Integer Dim nome As String'Variaveis das fontes Dim FonteNegrito As Font Dim FonteTitulo As Font Dim FonteSubTitulo As Font Dim FonteRodape As Font Dim FonteNormal As Font
FonteNegrito = New Font("Arial", 9, FontStyle.Bold)FonteTitulo = New Font("Arial", 15, FontStyle.Bold) FonteSubTitulo = New Font("Arial", 12, FontStyle.Bold) FonteRodape = New Font("Arial", 8) FonteNormal = New Font("Arial", 9)
LinhaAtual = 0 Dim L As Integer = 0
e.Graphics.DrawLine(CanetaDaImpressora, MargemEsquerda, 60, MargemDireita, 60)
e.Graphics.DrawLine(CanetaDaImpressora, MargemEsquerda, 160, MargemDireita,
160) e.Graphics.DrawString( My.Settings.Empresa, FonteTitulo, Brushes.Blue, MargemEsquerda + 250, 80, New StringFormat())
e.Graphics.DrawImage(Image.FromFile( "C:\teste\" & "maco10.gif"), 100, 68)
e.Graphics.DrawString(RelatorioTitulo & System.DateTime.Today,
FonteSubTitulo, Brushes.Black, MargemEsquerda + 250, 120,
New
StringFormat()) 'campos a serem impressos: Codigo e Nome e.Graphics.DrawString("Cod.", FonteNegrito, Brushes.Black, MargemEsquerda + 100, 170, New StringFormat()) e.Graphics.DrawString("Nome", FonteNegrito, Brushes.Black, MargemEsquerda + 200, 170, New StringFormat()) e.Graphics.DrawLine(CanetaDaImpressora, MargemEsquerda, 190, MargemDireita, 190)
LinhasPorPagina = CInt(e.MarginBounds.Height / FonteNormal.GetHeight(e.Graphics) - 9)
'Aqui sao lidos os dados While (LinhaAtual < LinhasPorPagina AndAlso Leitor.Read())
'obtem os valores do datareader codigo = Leitor.GetInt32(0) nome = Leitor.GetString(1)
'inicia a impressao PosicaoDaLinha = MargemSuperior + (LinhaAtual * FonteNormal.GetHeight(e.Graphics)) e.Graphics.DrawString(codigo.ToString(), FonteNormal, Brushes.Black, MargemEsquerda + 100, PosicaoDaLinha, New StringFormat())e.Graphics.DrawString(nome.ToString, FonteNormal, Brushes.Black, MargemEsquerda + 200, PosicaoDaLinha, New StringFormat()) LinhaAtual += 1 End While 'Rodape e.Graphics.DrawLine(CanetaDaImpressora, MargemEsquerda, MargemInferior, MargemDireita, MargemInferior) e.Graphics.DrawString(System.DateTime.Now.ToString(), FonteRodape, Brushes.Black, MargemEsquerda, MargemInferior, New StringFormat())LinhaAtual += CInt(FonteNormal.GetHeight(e.Graphics)) LinhaAtual += 1 e.Graphics.DrawString( "P gina : " & paginaAtual, FonteRodape, Brushes.Black, MargemDireita - 50, MargemInferior, New StringFormat())
'Incrementa o n£mero da pagina paginaAtual += 1
'verifica se continua imprimindo If (LinhaAtual > LinhasPorPagina) Thene.HasMorePages = TrueElse e.HasMorePages = False End If End Sub
|
E, finalmente a rotina para fechar o datareader e a conexão:
'Encerra a conexÆo e o
DataReader
Private
Sub End_Print(ByVal
sender As
Object,
ByVal byvale
As
Printing.PrintEventArgs)
Leitor.Close() MyConnection.Close() End Sub
|
Executando o projeto e clicando no ícone para imprimir temos:
Como o código esta comentado não nada a a acrescentar, a não ser informar que a variável Empresa que exibe o nome da empresa foi definida no arquivo de configuração da aplicação.
Como podemos ver o VB 2008 apresenta praticamente o mesmo resultado em relação a impressão de documentos. Quem sabe na nova versão alguma novidade boa neste sentido pode surgir , até lá vamos ter que fazer malabarismos para imprimir no VB se não quisermos usar nenhum gerador de relatório externo.
Agora para encerrar duas dicas legais recebidos do colega Ivo Closs:
Existe uma forma de deixar o menu (toolstrip) com uma aparência melhor (o original não tem apelo visual nenhum).
Basta inserir antes do ShowDialog() alguma linhas para mudar o estilo visual - veja script em negrito.
Dim newPrintPreviewDialog
As
New PrintPreviewDialog Try 'define o formulário como maximizado e com Zoom newPrintPreviewDialog.Document = newPrintDocument newPrintPreviewDialog.WindowState = FormWindowState.Maximized newPrintPreviewDialog.PrintPreviewControl.Zoom = 1 newPrintPreviewDialog.Text = "Relacao de Clientes" ' Seta o estilo visual CType(newPrintPreviewDialog.Controls(1), ToolStrip).RenderMode = ToolStripRenderMode.Professional CType(newPrintPreviewDialog.Controls(1), ToolStrip).GripStyle = ToolStripGripStyle.Visible 'CType(newPrintPreviewDialog.Controls(1), ToolStrip).Items.Item(0).Image = My.Resources.PrintToolStripMenuItem_Image 'CType(newPrintPreviewDialog.Controls(1), ToolStrip).Items.Item(1).Image = My.Resources.zoom CType(newPrintPreviewDialog.Controls(1), ToolStrip).Height = 25 newPrintPreviewDialog.ShowDialog() Catch ex As Exception MessageBox.Show(ex.ToString()) End Try
|
Uma dica para imprimir valores numéricos, alinhados à direita:
'imprime o código com alinhamento a direita
Pegue o projeto completo aqui: testeImpressao.zip
Eu sei é apenas VB.NET mas eu gosto.
Até o próximo artigo...
Veja os
Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique
e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ? |
Gostou ? Compartilhe no Facebook Compartilhe no Twitter
Referências: