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 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 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. Nomear um relatório no spool de impressão do WindowsInclua na seção uses: PrintersProblema: 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 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 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 Alterar (e restaurar) o tamanho da página na impressoraInclua 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 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 Saber se a impressora atual possui determinada fonteInclua 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 Página atualizada em 29 de outubro de 2012 |