C# - Editor de Texto com RichTextBox e PrintDocument - II


 No artigo de hoje vou mostrar como podemos criar um pequeno editor de textos usando os recursos do controle RichTextBox na linguagem C#. Veremos também como imprimir e visualizar a impressão do texto usando o PrintDocument.

Na primeira parte do artigo eu criei o projeto defini a interface com o usuário e implementei a maior parte das funcionalidades do editor de texto.

Neste artigo eu vou implementar as funcionalidades para exibir as configurações da impressora, visualizar a impressão e imprimir o texto carregado no editor.

  • Recursos usados:

    Implementando as opções de impressão do texto

    Abra  projeto RichTextBox_Imprimir criado no artigo anterior usando o VS Community 2013 clique em Open Project e selecione o projeto abrindo-o.

    Nesta parte iremos trabalhar com os componentes :

    Nesta opção exibimos as configurações da impressora padrão. Esta rotina atribui o componente PrintDialog ao documento a ser impresso: prntdlg1.Document = prntdoc1;

    Nota: Quando você cria uma instância de PrintDialog , as propriedades read/write são definidas para os valores iniciais os quais são:

    Propriedade Valor Inicial
    AllowSomePages false
    AllowPrintToFile true
    AllowSelection false
    Document null (Nothing no VB)
    PrinterSettings null (Nothing no VB)
    PrintToFile false
    ShowHelp false
    ShowNetwork true

    O diálogo é exibido usando o componente ShowDialog de maneira que o usuário pode definir as suas opções de impressão e decidir se imprime ou não o documento.

         private void mnuConfiguracoesImpressora_Click(object sender, EventArgs e)
         {
                ConfiguracoesImpressora();
         }

      private void toolStripConfigImpressora_Click(object sender, EventArgs e)
       {
               ConfiguracoesImpressora();
      }

          private void ConfiguracoesImpressora()
          {
                try
                {
                    this.prntdlg1.Document = this.prntdoc1;
                    prntdlg1.ShowDialog();
                }
                catch(Exception ex)
                {
                    MessageBox.Show("Erro : " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
          }

    Nesta opção usamos o componente PrintPreviewDialog para visualizar a impressão.

    O componente PrintPreview também dispara o evento PrintPage mas ao invés de direcionar para a impressora a saída é direcionada para a tela de visualização.

         private void mnuVisualizarImpressão_Click(object sender, EventArgs e)
         {
                visualizaImpressao();
         }

      private void toolStripVisualizar_Click(object sender, EventArgs e)
      {
              visualizaImpressao();
      } 
           private void visualizaImpressao()
           {
                //visualiza a impressao
                try
                {
                    string strTexto = this.rtxtb1.Text;
                    leitor = new StringReader(strTexto);
                    PrintPreviewDialog printPreviewDialog1 = new PrintPreviewDialog();
                    var prn = printPreviewDialog1;
                    prn.Document = this.prntdoc1;
                    prn.Text = "Macoratti - Visualizando a impressão";
                    prn.WindowState = FormWindowState.Maximized;
                    prn.PrintPreviewControl.Zoom = 1;
                    prn.FormBorderStyle = FormBorderStyle.Fixed3D;
                    prn.ShowDialog();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Erro : " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
           }

    Para realizar a impressão do documento usamos o método Print do componente PrintDocument.

    Para concluir a impressão precisamos definir o código no evento PrintPage.

    O evento PrintPage é automaticamente chamado pelo sistema para imprimir a página selecionada. O evento é do tipo PrintPageEventArgs  e contém o contexto do dispositivo e.Graphics usado para imprimir para a impressora.

    A propriedade PageBounds da classe PrintPageEventArgs representa um retângulo da página inteira , já a propriedade MarginBounds representa um retângulo da área do interior das margens conforme mostra a figura ao lado.

    Ambas as propriedades são usadas na unidade de 100 dpi, de maneira que um formato carta de 8.5 x 11 polegadas terá sempre um retângulo PageBounds de medida igual a {0, 0, 850, 1100}. Com uma margem padrão de 1 polegada , o retângulo MarginBounds terá as seguintes medidas {100, 100, 650, 900}.

    A margem é útil porque muitas impressoras não podem imprimir a partir do início das bordas das páginas. Para evitar a perda de impressão nestes casos o objeto Graphics que você manuseia quando você imprime, inicia a impressão no topo superior esquerdo da área de impressão da página.

    Neste exemplo efetuamos a leitura de cada linha de texto do controle RichTextBox usando um StringReader que nos dá a habilidade de tratar uma string como um stream e tomar vantagem da função ReadLine para ler cada linha de texto no controle.

    Podemos calcular a posição das linhas baseadas nas margens e na altura da fonte, e com o objetivo de prever a altura da fonte para a impressora nós passamos a ela o contexto do dispositivo da impressora na função GetHeight (printFont.GetHeight(ev.Graphics()), pois a altura da fonte na tela em pixels é diferente da fonte na impressora.

    O atributo HasMorePages da classe PrintPageEventArg é continuamente verificado de maneira que o evento PrintPage é disparado se existirem mais linhas do que a página atual pode suportar.

         private void mnuImprimir_Click(object sender, EventArgs e)
         {
                Imprimir();
         }

      private void toolStripImprimir2_Click(object sender, EventArgs e)
      {
                Imprimir();
      }

          private void Imprimir()
          {
                prntdlg1.Document = prntdoc1;
                string strTexto = this.rtxtb1.Text;
                leitor = new StringReader(strTexto);
                if (prntdlg1.ShowDialog() == DialogResult.OK)
                {
                    this.prntdoc1.Print();
                }
         }
         private void prntdoc1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
          {
                float linhasPorPagina = 0;
                float Posicao_Y = 0;
                int contador = 0;
                //defina as margens e o valor minimo
                float MargemEsquerda = e.MarginBounds.Left - 50;
                float MargemSuperior = e.MarginBounds.Top- 50;
                if (MargemEsquerda < 5)
                    MargemEsquerda = 20;
                if (MargemSuperior < 5)
                    MargemSuperior = 20;
                
               //define a fonte 
                string linha = null;
                Font FonteDeImpressao = this.rtxtb1.Font;
                SolidBrush meupincel = new SolidBrush(Color.Black);
                //StreamReader leitor = null;
                //Calcula o numero de linhas por página usando as medidas das margens
                linhasPorPagina = e.MarginBounds.Height / FonteDeImpressao.GetHeight(e.Graphics);
                // Vamos imprimir cada linha implementando um StringReader
                linha = leitor.ReadLine();
                while (contador < linhasPorPagina)
                {
                    // calcula a posicao da proxima linha baseado  na altura da fonte de acordo com o dispositivo de impressão
                    Posicao_Y = (MargemSuperior + (contador * FonteDeImpressao.GetHeight(e.Graphics)));
                    // desenha a proxima linha no controle richtextbox
                    e.Graphics.DrawString(linha, FonteDeImpressao, meupincel, MargemEsquerda, Posicao_Y, new StringFormat());
                    //conta a linha e incrementa uma unidade
                    contador += 1;
                    linha = leitor.ReadLine();
                }
                // se existir mais linhas imprime outra página
                if ((linha != null))
                {
                    e.HasMorePages = true;
                }
                else
                {
                    e.HasMorePages = false;
                }
                meupincel.Dispose();
         }

    Na opção Ajuda exibimos o formulário form2.cs que contém o seguinte leiaute e é composto pelos controles: PictureBox, GroupBox, Label, LinkLabel e Button.

    Para incluir o formulário no projeto clique no menu PROJECT -> Add Windows Forms; (Abaixo a direita vemos o código do form2.cs)

        private void lnkurl_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
           {
                lnkurl.LinkVisited = true;
                System.Diagnostics.Process.Start("http://www.macoratti.net");
           }
           private void btnFechar_Click(object sender, System.EventArgs e)
           {
                this.Close();
           }

     

    Abaixo temos o código do formulário form1.cs que chama o método Sobre() para exibir o formulário form2.cs acima:

      private void mnuSobre_Click(object sender, EventArgs e)
       {
                Sobre();
       }

          private void toolStripAjuda_Click(object sender, EventArgs e)
           {
                Sobre();
           }

      private void Sobre()
       {
                try
                {
                    Form2 frm2 = new Form2();
                    frm2.ShowDialog();
                    if (frm2.DialogResult == DialogResult.OK)
                    {
                        frm2.Dispose();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Erro : " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
      }

    A opção Sair solicita ao usuário a confirmação para encerrar ou não a aplicação.

         private void sairToolStripMenuItem_Click(object sender, EventArgs e)
         {
                Sair();
         }
        private void toolStripSair_Click(object sender, EventArgs e)
        {
             Sair();
        }

          private void Sair()
          {
                if(MessageBox.Show("Deseja sair da aplicação ?","Sair",MessageBoxButtons.YesNo,MessageBoxIcon.Question)== System.Windows.Forms.DialogResult.Yes)
                {
                    Application.Exit();
                }
          }

    E assim temos as funcionalidades do nosso editor implementadas e prontas para serem usadas. Eu poderia continuar incluindo mais funcionalidades como o Refazer (Redo), Desfazer (Undo), etc. ,  mas deixo como exercício para você.

    Executando o projeto temos uma visão do nosso editor em funcionamento abaixo:

    Pegue o projeto completo aqui : RichTextBox_Imprimir.zip

    E Deus limpará de seus olhos toda a lágrima; e não haverá mais morte, nem pranto, nem clamor, nem dor; porque já as primeiras coisas são passadas.
    Apocalipse 21:4

    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 ?

      Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

    Referências:


    José Carlos Macoratti