Delphi@Brasil Magazine - Abril 98


Tópico do mês : Criar uma rotina que imprima em formulários pré-impressos do tipo nota fiscal ou bloquete bancário.

- Sem dúvida alguma, esse é o tópico campeão de dúvidas enviadas pelos leitores, por esse motivo decidi investigá-lo para oferecer aos nossos leitores uma solução, que pode não ser a ideal, porém acredito preencher bastante nossas necessidades.

- O problemas consiste em localizar caracteres dentro de medidas exatas, em conformidade com a sua localização na página, e em relação ao começo da outra página. A solução que vou apresentar aqui é tão simples que o leitor vai se perguntar por que não pensou nisso antes ?!?

- Vamos fazer uso de localização relativa, ou seja ao invés de localizarmos com quantos caracteres ou quantas linhas nossa string vai ser escrita, vamos dizer em termos percentuais em relação à página que estamos usando onde será escrita nossa string. Por exemplo : Se queremos escrever uma palavra no meio de uma página(não importando o tamanho desta, ou mesmo da fonte), só necessitamos pedir ao delphi que escreve a palavra à 50% da altura da página e 50% da largura da mesma. Note que com isso matamos a preocupação de saber quantas linhas por exemplo seriam necessárias pular para se chegar ao ponto, já que por essa visão, ao mudarmos a fonte que usamos por exemplo, nossa impressão vai sair errada. Bem já falamos muito vamos dar uma olhada inicialmente na figura I.

 

Figura I

- A localização das fontes a partir da chamada na função de Canvas.TextOut se dá da forma mostrada na figura I, ou seja, se queremos imprimir uma letra no início da página basta colocarmos uma chamada do tipo : Printer.Canvas.TextOut('D', 0, 0); Só que deste modo teremos que saber quantos pontos são necessários até o meio da página por exemplo, se queremos imprimir à 50% da página como no início da matéria. Para contornarmos este problema vamos escrever uma função genérica no nosso aplicativo teste chamada imprime.

Procedure TForm1.Imprime(nX, nY : Integer; cFrase : String);
begin
With Printer do
Canvas.TextOut( Trunc(PageWidth * ( nX / 100)), Trunc(PageHeight * ( nY / 100)), cFrase);
end;

- Lembre-se de incluir uma referência a esta função na parte Public de TForm1. Note também que não colocamos nenhum claúsula de tratamento de erros por ser um aplicativo teste, porém em situações normais de uso é essencial uma chamada a Try pois estamos manipulando com impressoras, e o usuário(inclusive nós mesmos programadores), gostamos de desligar a impressora no meio da impressão para não gastarmos mais tinta e/ou papel quando queremos interromper uma impressão já iniciada.

- Como podemos ver nossa função recebe três argumentos : nX e nY que serão as localizão relativas na página e cFrase que é a string a ser impressa. Repare como usamos as propriedades PageWidth e PageHeight de Printer para sabermos em que ponto da página vamos imprimir em termos percentuais. Por exemplo para imprimirmos à 50% de X numa página que possui 1200 pontos de comprimento nos temos que : 1200(50/100) = 600, ou seja nossa frase vai ser escrita no ponto de número 600 da página.

- Agora vamos dar uma funcionalidade real ao nosso aplicativo. Inclua todos os elementos como mostrado na figura II.

 

Figura II

- No manipulador on Click do nosso TBitBtn de Configura Impressora, coloque uma chamada a execute de PrinterSetupDialog assim :

PrinterSetupDialog1.Execute;

- Se você rodar o aplicativo o Delphi informa que o objeto TPrint é não identificado, isso porque a unit Printers não é padrão do Delphi, então nós temos que incluir manualmente uma chamada à ela no uses com Printers.

- No manipulador de nosso TBitBtn de Imprime coloque o código como está abaixo :

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
With Printer do
begin
BeginDoc;
Self.Imprime(StrToInt(Edit1.Text),StrToInt(Edit2.Text), Edit3.Text);
EndDoc;
end;

end;

- E está pronto o nosso aplicativo de teste. É só executá-lo e lançar parâmetros para teste. Mais uma vez lembro que este é um aplicativo teste, por isso não colocamos nenhum tratamento de erro, por exemplo na transformação de String para integer em StrToInt do TEdit.

- E agora você me pergunta, Como faço para encaixar meus dados num formulário pré-impresso ? Simples, meça o tamanho total do papel(de preferência em mm., mas pode ser em polegadas também), largura e altura, e meça cada um dos seus campos, na horizontal e vertical, e depois faça o quociente entre os dois e coloque-os como parâmetro de nossa função. Por exemplo : nossa página mede 210 mm de largura e 320 mm de altura, já o campo a ser impresso está localizado à 30 mm na horizontal e 50 mm na vertical, então nosso parâmetros serão : nX = 30/210 = 0,142 ~ 14% da largura, e nY = 50/320 = 0,156 ~ 15% da altura. Coloque esses parâmetros no nosso aplicativo e mande imprimir como podemos visualizar na figura III.

Figura III

- Se você executou todos os passos corretamente ele será impresso, mas aí você me pergunta, e se o tamanho da página não for o padrão como o de notas fiscais ou bloquetes bancários, o que faço ?. Você simplesmente entra no menu impressoras e cria uma nova impressora com o nome por exemplo de notas fiscais, onde no tamanho da página você vai colocar a opção "Tamanho definido pelo usuário", então serão solicitados os dados de medida da página e aí você entra com os tais dados como vemos na figura IV.

Figura IV

- Veja que a medida está em 0,1 mm, por isso se temos uma página com largura de 210 mm ou 21 cm temos de colocar 2100 na largura indicada na figura IV.

- Agora quando você for imprimir basta selecionar a impressora Notas Fiscais e a impressora já estará configurada para o papel. Neste momento surge um problema que muitos dos leitores já devem ter se deparado. Simplesmente o caixa de diálogo do setup da impressora parece não funcionar quando escolhemos uma impressora que não a padrão do windows. Isso é um Bug do Delphi, você não está fazendo nada de errado !, afinal ainda não sei porque a Borland não solucionou este problema pois eu estou usando o Delphi 3 com os "patches" fornecidos pela Borland e até agora nada. Para corrigirmos este bug basta alterarmos o código da TBitBtn que chama o método execute para o mesmo que vemos abaixo :

procedure TForm1.ConfiguraImpressora1Click(Sender: TObject);
Var
Driver, Device, Port : array[0..79] of char;
Mode : THandle;
begin
Printer.GetPrinter(Driver, Device, Port, Mode);
Printer.SetPrinter(Driver, Device, Port, 0);
PrinterSetupDialog1.Execute;
end;

- Veja que antes de chamarmos nosso execute, chamamos funções da API do windows para manipular o dispositivo do windows que está como impressora atual.

- A matéria deste mês acredito que venha de encontro que o anseio de centenas de programadores pelo quantidade de mails que recebi com dúvidas relacionadas a isto, por isso espero que a mesma sirva como um auxílio inicial para nossos leitores desenvolverem suas própiras rotinas. Venho reforçar o pedido para que se desejarem entrem em contato conosco por meio de [email protected] , e também lembrá-los que estamos abertos a publicar matérias vindas de nossos leitores para que desse modo possamos melhorar ainda mais os nossos serviços para os leitores e servir de vitrine para o autor da matéria.

 

Fúlvio C. Albuquerque

Editor responsável

Hosted by www.Geocities.ws

1