Você sabe muito bem que tempo é dinheiro. Mas, André, o que isso tem a ver com o artigo de hoje? Tem tudo a ver! Muitos usuários de sistemas não querem ficar perdendo tempo vendo o preview da impressão se eles sabem exatamente o que vai ser impresso. Acontece com usuários das aplicações que eu desenvolvi e garanto que deve acontecer com os usuários da sua aplicação. Tanto é que um dos inscritos da minha newsletter sugeriu que eu abordasse a impressão direto na impressora com C#. E eu pensei: por que não?
Imprimindo texto direto na impressora
Definitivamente, o conteúdo mais simples de se imprimir diretamente na impressora é texto, especialmente se for tudo com uma fonte só. Nesse primeiro exemplo, quero demonstrar justamente como você pode imprimir um bloco de texto direto na impressora, sem nenhum preview.
Para isso, crie um novo projeto do tipo “Windows Forms Application“. Com esse novo projeto criado, ajuste o formulário de forma que ele fique parecido com a imagem abaixo:
Como você pode perceber, temos um ComboBox para escolher a impressora a ser utilizada (impressoraComboBox), um botão que será responsável por disparar a impressão (imprimirButton) e um TextBox com o conteúdo que deverá ser impresso (impressaoTextBox). Não esqueça de configurar o TextBox para que ele suporte múltiplas linhas (propriedade Multiline).
Antes de partirmos para o código da impressão, temos que carregar a lista de impressoras. Você não tem noção de quão fácil é listar as impressoras instaladas com o .NET Framework. A classe PrinterSettings tem uma propriedade estática chamada InstalledPrinters, que nada mais é que uma lista de strings com os nomes das impressoras. Mais simples impossível!
Dito isso, crie um método no nosso formulário (chamado CarregarListaDeImpressoras) e faça a chamada desse método no construtor do formulário:
public FormImpressaoDireta() { InitializeComponent(); CarregarListaDeImpressoras(); } private void CarregarListaDeImpressoras() { impressoraComboBox.Items.Clear(); foreach (var printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters) { impressoraComboBox.Items.Add(printer); } }
Feito isso, vamos implementar o código para fazer a impressão do texto direto na impressora, sem o preview. A classe que temos que utilizar para implementar essa funcionalidade é a PrintDocument. Essa classe utiliza o evento PrintPage para gerenciar a impressão, ou seja, na implementação desse evento, você precisa controlar o que deve ser impresso em cada uma das páginas:
private void imprimirButton_Click(object sender, EventArgs e) { using (var printDocument = new System.Drawing.Printing.PrintDocument()) { printDocument.PrintPage += printDocument_PrintPage; printDocument.PrinterSettings.PrinterName = impressoraComboBox.SelectedItem.ToString(); printDocument.Print(); } } void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { var printDocument = sender as System.Drawing.Printing.PrintDocument; if (printDocument != null) { using (var font = new Font("Times New Roman", 14)) using (var brush = new SolidBrush(Color.Black)) { e.Graphics.DrawString( impressaoTextBox.Text, font, brush, new RectangleF(0, 0, printDocument.DefaultPageSettings.PrintableArea.Width, printDocument.DefaultPageSettings.PrintableArea.Height)); } } }
Para testar o código, execute a aplicação, escolha uma impressora no ComboBox, digite um texto na caixa de texto e clique em “Imprimir“:
A propósito, você sabia que o Word consegue gerar textos de exemplo (esse que começa em “Lorem ipsum“)? Aprenda como neste link.
E se não couber em uma página?
Se o conteúdo da caixa de texto não couber em uma página, somente a primeira página será impressa. E como conseguimos ajustar o código para que ele se comporte corretamente independentemente do número de páginas? Para isso, temos que alterar um pouco o código de forma que somente o texto que cabe em cada página seja impresso. Como fazer isso? Veja o resultado:
private string _texto; private void imprimirButton_Click(object sender, EventArgs e) { using (var printDocument = new System.Drawing.Printing.PrintDocument()) { printDocument.PrintPage += printDocument_PrintPage; printDocument.PrinterSettings.PrinterName = impressoraComboBox.SelectedItem.ToString(); _texto = impressaoTextBox.Text; printDocument.Print(); } } void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { var printDocument = sender as System.Drawing.Printing.PrintDocument; if (printDocument != null) { using (var fonte = new Font("Times New Roman", 14)) using (var brush = new SolidBrush(Color.Black)) { int caracteresNaPagina = 0; int linhasPorPagina = 0; e.Graphics.MeasureString( _texto, fonte, e.MarginBounds.Size, StringFormat.GenericTypographic, out caracteresNaPagina, out linhasPorPagina); e.Graphics.DrawString( _texto.Substring(0, caracteresNaPagina), fonte, brush, e.MarginBounds); _texto = _texto.Substring(caracteresNaPagina); e.HasMorePages = _texto.Length > 0; } } }
Como você pode ver, agora temos uma “variável” no nível do formulário chamada “_texto“. Essa variável guardará sempre o texto que está faltando imprimir. Portanto, quando clicamos no botão “Imprimir“, nós guardamos o texto completo da caixa de texto nessa variável. Depois, conforme formos imprimindo o texto de cada página, iremos ajustando o valor dessa variável para que ela guarde somente o texto que está faltando.
E como é que medimos a quantidade de texto que cabe em uma página? Fácil! É só utilizarmos o método MeasureString da classe Graphics. Esse método recebe o texto, a fonte e as dimensões da área disponível para impressão, retornando a quantidade de caracteres e linhas que conseguimos imprimir nessa área:
int caracteresNaPagina = 0; int linhasPorPagina = 0; e.Graphics.MeasureString( _texto, fonte, e.MarginBounds.Size, StringFormat.GenericTypographic, out caracteresNaPagina, out linhasPorPagina);
Por fim, a outra alteração importante na implementação do evento PrintPage foi feita na última linha, onde indicamos se ainda temos outra página para imprimir ou não (propriedade HasMorePages). Devemos configurar essa propriedade como “true” caso ainda tenhamos texto para ser impresso (Length maior que zero).
Imprimindo imagens e formas geométricas
Da mesma forma que conseguimos imprimir texto utilizando a classe PrintDocument, nós conseguimos imprimir imagens e formas geométricas também. Para isso, ao invés de utilizarmos o método DrawString, temos que utilizar os métodos DrawImage ou Draw*** (onde “***” é o nome da figura geométrica que você quer desenhar).
Por exemplo, para imprimirmos uma imagem do arquivo “logo.png” (localizada no mesmo diretório da aplicação), poderíamos utilizar o seguinte código:
void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { var printDocument = sender as System.Drawing.Printing.PrintDocument; if (printDocument != null) { e.Graphics.DrawImage(Image.FromFile("logo.png"), new Point(5, 5)); } }
Já para imprimirmos um polígono qualquer, temos que substituir a chamada do método DrawImage por DrawPolygon:
e.Graphics.DrawPolygon( new Pen(Color.Red), new[] { new Point(30, 30), new Point(80, 150), new Point(20, 70), new Point(100, 100), new Point(30, 30) });
Imprimindo um RichTextBox formatado
O exemplo de impressão de texto que eu demonstrei nesse artigo não considera a impressão de textos ricos (com formatação). Para conseguirmos imprimir esse tipo de texto com formatação, é necessária muita gambiarra. Durante a minha pesquisa para escrever esse artigo, encontrei dois exemplos de impressão de RichTextBox:
Getting WYSIWYG Print Results from a .NET RichTextBox
How to print the content of a RichTextBox control by using Visual C# .NET or Visual C# 2005
Impressão matricial
Algumas pessoas já me perguntaram como fazer para imprimir diretamente na porta LPT1, a fim de imprimir texto puro em impressoras matriciais. Sempre que alguém me pergunta isso, eu encaminho o link para o componente que o Carlos dos Santos desenvolveu, que implementa justamente essa funcionalidade:
Dot Matrix Print 2.0 – Componente para impressão matricial
Concluindo
Normalmente, quando queremos imprimir informações a partir dos nossos sistemas, utilizamos alguma ferramenta de geração de relatórios (como Report Viewer ou Crystal Reports). Porém, em algumas situações precisamos ter o controle total do conteúdo que será impresso, principalmente as posições onde as informações serão impressas e se queremos ou não exibir um preview antes de imprimir. Nesse artigo você aprendeu a imprimir textos, imagens e figuras geométricas diretamente na impressora. Dessa forma, nas situações em que você precisar desse tipo de controle total da sua impressão, você saberá como proceder.
E você, já teve que fazer algo parecido? Como você acabou resolvendo essa situação? Da mesma forma que eu resolvi ou de alguma outra maneira? Conte nos comentários como foram as suas experiências com a impressão de informações em aplicativos desenvolvidos com o .NET Framework.
Antes de me despedir, convido você a inscrever-se na minha newsletter. Ao fazer isso, você receberá um e-mail toda semana sobre o artigo publicado, ficará sabendo em primeira mão sobre o artigo da próxima semana e receberá também dicas “bônus” que eu só compartilho por e-mail. Além disso, você já deve ter percebido que eu recebo muitas sugestões de temas e eu costumo dar prioridade às sugestões vindas de inscritos da minha newsletter. Inscreva-se aqui ou utilizando o formulário logo abaixo.
Até a próxima!
André Lima
The post Impressão direto na impressora com C# appeared first on André Alves de Lima.