Dicas de Delphi - Impressão


Imprimir Memo (2)

Inclua na seção uses: Printers
Já vimos em outra dica como imprimir um memo acessando a 
impressora como se fosse um arquivo. Aqui usaremos outra 
técnica. Vamos usar o objeto Printer e "desenhar" na 
impressora usando Canvas. Esta técnica, dentre outras coisas, 
nos permite controlar:

- Salto de página;
- Espaçamento entre linhas;
- Margens, etc.

Veja esta rotina:

procedure ImprimirMemoComCanvas(Memo: TMemo);
const
  cEspacoLinha = 5;
  cMargemSuperior = 50;
  cMargemEsquerda = 30;
var
  AlturaLinha, Y, I: integer;
begin

  Printer.BeginDoc;
  try
    { Usa na impressora a mesma fonte do memo }
    Printer.Canvas.Font.Assign(Memo.Font);

    AlturaLinha := Printer.Canvas.TextHeight('Tg');

    Y := cMargemSuperior;
    for I := 0 to Memo.Lines.Count -1 do begin

      if Y > Printer.PageHeight then begin
        Printer.NewPage;
        Y := cMargemSuperior;
      end;

      Printer.Canvas.TextOut(cMargemEsquerda, Y, Memo.Lines[I]);

      Y := Y + AlturaLinha + cEspacoLinha;
    end;
  finally
    Printer.EndDoc;
  end;
end;

É um exemplo simples, mas funcional. Para testar chame esta 
rotina passando o objeto TMemo como parâmetro. Exemplo:

ImprimirMemoComCanvas(Memo1);

Observações

A grande vantagem em usar o objeto Printer é que ele nos dá total liberdade para desenhar na impressora. Podemos, por exemplo, desenhar elipses, retângulos, etc. A principal desvantagem é que o programador precisa trabalhar muito para obter a impressão desejada. Mas às vezes vale a pena!

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início


Imprimir Memo (1)

Inclua na seção uses: Printers
Para imprimir um campo memo (objeto TMemo) podemos usar 
diversos métodos. Um deles é acessar a impressora como se
fosse um arquivo. Para isto é necessário atribuir a impressora
a uma variável arquivo (AssignPrn), abrir o arquivo (ReWrite),
escrever nele (write e writeln) e finalmente fechar o 
arquivo (CloseFile). Talvez seja mais fácil entender o que 
estou dizendo estudando a rotina abaixo.

procedure ImprimirMemo(Memo: TMemo);
var
  I: integer;
  F: Text;
begin
  { Usa na impressora a mesma fonte do memo }
  Printer.Canvas.Font.Assign(Memo.Font);

  AssignPrn(F);
  Rewrite(F);
  try
    for I := 0 to Memo.Lines.Count -1 do
      WriteLn(F, Memo.Lines[I]);
  finally
    CloseFile(F);
  end;
end;

Para imprimir um memo com esta rotina basta chamá-la passando
como parâmetro o objeto TMemo. Exemplo:

ImprimirMemo(Memo1);

Observações

Este método está longe de ser perfeito, mas quebra um galho. Uma alternativa que oferece mais precisão na impressão é usar o Canvas do objeto Printer (Printer.Canvas), mas isto será alvo de outra dica. Outra alternativa bastante prática é usar os recursos de um gerador de relatórios (exemplo: QuickReport). Eu particularmente não sou fã do QuickReport!

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início


Verificar se a impressora está ligada

Problema:

Faço impressão direta para a porta da impressora e gostaria
testar se a impressora está pronta antes de enviar o 
relatório. Isto é possível em Delphi?

Solução:

Usando instruções Assembly podemos fazer isto. A função
abaixo retorna true se a porta informada está pronta.

Os possíveis parâmetros para esta função são:
1 - para LPT1
2 - para LPT2
3 - para LPT3
4 - para LPT4

function tbTestLPT(Port: byte): boolean;
var
  Pto : Word;
  Rdo : byte;
begin
  Pto := Port -1;
  asm
    MOV  DX,Pto
    MOV  AX,$0200  {AH := $02 : Leer el estado de la impresora}
    INT  $17
    MOV  Rdo,AH     {Guarda el estado en AL}
  end;
  Result := Rdo = 144;
end;

Observações

Provavelmente esta função não funcionará em Windows NT devido ao acesso em baixo nível.

Início


Nomear um relatório no spool de impressão do Windows

Inclua na seção uses: Printers
Problema:

Quando mandamos imprimir no Windows, normalmente o nome do 
documento aparece na fila de impressão (spool). Como fazer
com que aplicativos feitos em Delphi se comporte desta
forma? Ou seja, como nomear meus relatórios feitos em Delphi?

Solução:

Antes de enviar seu relatório, faça assim:

Printer.Title := 'Nome do relatório';

Observações

Esta solução aplica-se perfeitamente aos relatórios feitos usando o objeto Printer. Nos casos de geradores de relatórios, estes provavelmente possuem uma propriedade equivalente.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início


Imprimir caracteres acentuados diretamente para a impressora

{ Usando comandos da impressora podemos fazer isto de uma
  forma bastante simples. Quando enviamos o caractere ASCII
  número 8 (oito) para a impressora, a cabeça de impressão 
  retrocede uma posição, pois este caractere é o BackSpace.
  Então podemos imprimir a letra sem acento e, sem seguida,
  voltar e imprimir o acento desejado. Vejamos um exemplo:

  - Coloque um botão no form;
  - Altere o evento OnClick deste botão conforme abaixo:
}

procedure TForm1.Button2Click(Sender: TObject);
var
  F: TextFile;
begin
  AssignFile(F, 'LPT1');
  Rewrite(F);
  try
    { Regra: caractere sem acento + chr(8) + acento }
    WriteLn(F, 'Este e' + #8 + '''' + ' um teste.');
    WriteLn(F, 'Acentuac' + #8 + ',a' + #8 + '~o.');
    WriteLn(F, 'Vovo' + #8 + '^');
    WriteLn(F, 'U' + #8 + '''' + 'ltimo.');
    WriteLn(F, #12); // Eject
  finally
    CloseFile(F);
  end;
end;

Observações

Usando este recurso, a acentuação não fica excelente, mas melhora bastante.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início


Imprimir texto justificado com formatação na impressora Epson LX-300

{ A impressora Epson LX-300 dispõe de um comando que justifica
  o texto. Este recurso é interessante, pois com ele podemos
  continuar a enviar os comandos de formatação de caracteres
  como condensado, negrito, italico, expandido, etc.

  Para o exemplo abaixo:
  - Coloque um botão no form;
  - Altere o evento OnClick deste botão como abaixo: }

procedure TForm1.Button1Click(Sender: TObject);
const
  cJustif     = #27#97#51;
  cEject      = #12;

  { Tamanho da fonte }
  c10cpi      = #18;
  c12cpi      = #27#77;
  c17cpi      = #15;
  cIExpandido = #14;
  cFExpandido = #20;
  { Formatação da fonte }
  cINegrito   = #27#71;
  cFNegrito   = #27#72;
  cIItalico   = #27#52;
  cFItalico   = #27#53;
var
  Texto: string;
  F: TextFile;
begin
  Texto := c10cpi +
    'Este e um teste para impressora Epson LX 300. ' +
    'O objetivo e imprimir texto justificado sem deixar ' +
    'de usar formatacao, tais como: ' +
    cINegrito + 'Negrito, ' + cFNegrito +
    cIItalico + 'Italico, ' + cFItalico +
    c17cpi + 'Condensado (17cpi), ' + c10cpi +
    c12cpi + '12 cpi, ' + c10cpi +
    cIExpandido + 'Expandido.' + cFExpandido +
    ' Este e apenas um exemplo, mas voce podera adapta-lo ' +
    'a sua realidade conforme a necessidade.';

  AssignFile(F, 'LPT1');
  Rewrite(F);
  try
    WriteLn(F, cJustif, Texto);
    WriteLn(F, cEject);
  finally
    CloseFile(F);
  end;
end;

Observações

Este recurso de justificação da Epson LX-300 pode ser usado em qualquer linguagem de programação.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início


Alterar (e restaurar) o tamanho da página na impressora

Inclua na seção uses: tbPrn
{ - Peque em nosso Download o arquivo tbPrn.zip. Ele contém
    a unit tbPrn.pas, onde está a função tbPrnSetPaperSize 
    usada no exemplo abaixo;

  - Adicione a unit tbPrn.pas em seu projeto;

  - Siga o exemplo abaixo para criar seus relatórios
    usando o TPrinter.
}

procedure TForm1.Button1Click(Sender: TObject);
var
  Papel: TtbPrnPaper;
begin
  Papel.Size := 256; // 256 é o tam. personalizado
  Papel.Width := 2100; // 21 cm
  Papel.Height := 1000; // 10 cm
  Papel := tbPrnSetPaperSize(Papel);
  try
    Printer.BeginDoc;
    try
      { coloque aqui os comandos para impressão }
    finally
      Printer.EndDoc;
    end;
  finally
    tbPrnSetPaperSize(Papel); // Restaura o tamanho
  end;
end;

{ Papel.Size refere-se ao tamanho do papel. Veja alguns:
    0 - Default
    1 - Letter
    5 - Legal
    8 - A3
    9 - A4
   11 - A5
  256 - Custom (personalizado) }

Observações

Só será necessário informar Papel.Height e Papel.Width quando Papel.Size for 256.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início


Definir a quantidade de registros a ser impressa em uma página do QuickReport

Ou seja, gostaria que, ao visualizar ou imprimir um relatório
do Quick Report, saia em cada página apenas um registro,
mesmo que o espaço permita mais de um.

Existem pelo menos duas formas de resolver este problema:

1. A forma mais simples consiste em alterar a altura (Height)
   da banda Detail do nosso relatório de modo que a altura
   total da página seja inferior a duas vezes a altura da banda.
   Desta forma, cada registro será impresso em uma nova página,
   teoricamente por falta de espaço na página atual.

2. Uma outra forma mais sofisticada é usar o evento AfterPrint
   da banda Detail. Nele testamos se ainda não chegou no fim 
   da tabela e, caso positivo, pedimos uma nova página:

   if not Table1.EOF then
     QuickRep1.NewPage;

Deve existir outras alternativas, mas as duas anteriores
funcionaram bem nos testes realizados.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início


Saber se a impressora atual possui determinada fonte

Inclua na seção uses: Printers
{ Coloque este código no OnClick de um botão }
with Printer.Fonts do
  if IndexOf('Draft 10cpi') >= 0 then
    ShowMessage('A impressora possui a fonte.')
  else
    ShowMessage('A impressora NÃO possui a fonte.');

Observações

Isto pode ser útil quando queremos usar fonte da impressora quando for uma matricial ou fonte do Windows quando for uma Jato de Tinta ou Laser.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início


Página atualizada em 17 de dezembro de 2014
Todos os direitos reservados
www.tecnobyte.com.br