Quando comecei a usar a win_prn, tive varias dificuldades, entao fiz uma biblioteca de inumeras funcoes que tem me ajudado a programar impressoes A4 mais facilmente. O principal objetivo desta biblioteca era parar de pensar em pixels e só pensar em linhas e colunas de texto. E abaixo vou copiar umas anotacoes que deixei dentro do prg sobre essa questão de tamanho de fonte, porque conforme eu ia descobrindo as coisas eu ia anotando.
* No metodo SetFont o terceiro parametro é um array que define o nr de caracteres por polegada (segundo elemento dividido pelo
* primeiro).
* Porem, nao consegui entender essa matematica, pois nesse caso {1,11.5} deveria ser igual a {3,34.5}, mas não é: produz
* resultados diferentes quando o segundo elemento não é inteiro.
* Descobri que o primeiro elemento muito pequeno, como 1, não fica preciso, e melhora a precisao quando voce aumenta.
* Por isso, como não sei quanto teria que aumentar, botei 200 logo. Assim, as margens desejadas em milimetros ficaram
* praticamente perfeitas com qualquer tamanho de fonte e nr de colunas.
* Obs.: Definir :CharWidth diretamente com o terceiro parametro numerico em vez de array, tambem nao funcionou.
* Só funcionou precisamente assim: array com um divisor alto.
Vou postar a biblioteca inteira pra ver se serve pra alguem. Eu to usando bastante, porque só preciso definir no inicio as margens esquerda e direita em milimetros, o tamanho da fonte e o nr de colunas que quero na impressao e depois disso, tudo é linha e coluna de texto. Eu acho mais facil assim. Pixel é um saco. E lidar com margens tambem é um saco. Assim depois de defini-las no inicio em milimetros, as colunas vao de 1 a ultima sem mais delongas.
Código: Selecionar todos
/*
Biblioteca EP (Easy Print)
Conjunto de funcoes EP_xxxxx de auxilio para impressao via classe WIN_PRN.
Criada para facilitar a criação de relatorios diversos usando LINHAS E COLUNAS DE TEXTO, para que o programador não se
preocupe muito com margens ou pixels.
Melhor para impressoes em A4 com fonte de tamanho fixo (monoespacadas). É possivel usar fontes nao-fixas mas essa biblioteca
foi desenvolvida para posicionamentos mais fáceis com uso de linhas e colunas de texto, e com um numero de colunas pre-definido
terminando na margem direita pre-definida em milimetros.
Se usar uma fonte não-fixa saiba que o posicionamento de coluna feito por EP_Goto ou :SetPrc não são precisos.
Porém, as impressões feitas pelas funções EP_Say0C, EP_Say0L ou EP_Say0R não são afetadas pelo uso de fontes não fixas, desde que
voce use o posicionamento baseado em LINES desenhadas. Se estiver usando uma fonte não-fixa, ao usar estas funções, use este tipo
de posicionamento, ao invés de colunas de texto.
Para uso desta biblioteca, inicie seu trabalho de impressao com:
EP_StarJob( Impressora , nMilimetrosMargemEsquerda , nMilimetrosMargemDireita )
EP_SetFont( FonteDesejada , TamanhoDaFonte , NrDeColunasDesejado )
EP_Goto(1,1)
A partir daí, basta imprimir livremente usando as funcoes, sem se preocupar com margens ou pixels.
Tudo é baseado em linhas e colunas de texto dentro das margens definidas, inclusive desenho de linhas, boxes, ou imagens.
As linhas vão de 1 a EP_MaxRow() e as colunas de 1 ao numero de colunas que voce definiu.
Os metodos originais da classe consideram primeira coluna como zero, mas essas funcoes NAO SEGUEM O MESMO RACIOCINIO:
Nessas funcoes linha e coluna começam em 1.
O objetivo dessas funcoes é para que o programador só trabalhe com LINHAS E COLUNAS DE TEXTO e sem se preocupar com margens.
A unica excecao fica por conta de um eventual ajuste fino do desenho (draw) de linhas e boxes, se achar necessario.
Esse ajuste fino é feito em pixels, mas se nao quiser, pode usar o posicionamento normal baseado nas colunas de texto.
Relacao das funcoes criadas:
EP_StartJob // Inicio de cada relatorio, definicao de impressora, margens e largura do papel
EP_SetFont // Definicao de fonte e nr de colunas do relatorio
EP_Goto // Posiciona
EP_CRLF // Carriage Return + Line Feed - Passa para o inicio da proxima linha
EP_Negrito // Liga/Desliga
EP_Sublinhado // Liga/Desliga
EP_Italico // Liga/Desliga
EP_Prow // Nr da linha logica atual
EP_Pcol // Nr da coluna logica atual
EP_MaxRow // Maior linha logica
EP_MaxCol // Maior coluna logica
EP_Say1 // Imprime texto no inicio da proxima linha
EP_Say0 // Imprime texto na linha atual a partir da posicao atual
EP_Say0C // Imprime texto na linha atual centralizado
EP_Say0L // Imprime texto na linha atual encostado a esquerda
EP_Say0R // Imprime texto na linha atual encostado a direita
EP_EndJob // Finaliza e destroi o Job
EP_Eject // Inicia uma nova pagina
EP_SetLinha // Define a altura da linha independente da altura da fonte
EP_PrintImage // Imprime uma imagem
EP_LinhaHorizontal // Desenha uma linha horizontal
EP_LinhaVertical // Desenha uma linha vertical
EP_Box // Desenha um box
EP_Elipse // Desenha uma elipse
EP_Circle // Desenha um circulo
EP_XToCol // Converte pixel X em nr de coluna logica.
EP_ColToX // Converte coluna logica em pixel X
EP_YToRow // Converte pixel Y em nr de linha
EP_RowToY // Converte linha em pixel Y
Ver as explicacoes, parametros, etc de cada funcao na construção da propria.
VARIAVEIS PUBLICAS CRIADAS E QUE PODEM SER USADAS SE QUISER:
(Normalmente nao é necessario utiliza-las)
oJob // Objeto de impressao
EP_MEsquerdaMM // Margem esquerda em milimetros que voce definiu
EP_MDireitaMM // Margem direita em milimetros que voce definiu
EP_LarguraPapelMM // Largura do papel em milimetros
EP_NC // Nr de colunas do relatorio que voce informou no ultimo EP_SetFont
EP_CW // Largura do caractere (o mesmo que oJob:CharWidth)
EP_LH // Altura da linha (o mesmo que oJob:LineHeight)
EP_PrimeiroXUtil // Primeiro pixel do eixo X (colunas) da area util do relatorio
EP_UltimoXUtil // Ultimo pixel do eixo X (colunas) da area util do relatorio
EP_PrimeiroYUtil // Primeiro pixel do eixo Y (linhas) da area util do relatorio
--------------------------------------------------------------------------------------------------------------
Só use diretamente algum metodo da classe WIN_PRN se ele não tiver similar nesta biblioteca.
Fora isso, os metodos podem ser usados normalmente com o objeto oJob.
O METODO :SETPRC NAO DEVE SER USADO NA MESMA PAGINA QUE A FUNCAO EP_GOTO, POIS SEUS POSICIONAMENTOS NAO SAO IGUAIS.
NÃO USE :NEWPAGE, USE EP_EJECT().
NÃO USE :NEWLINE, USE EP_CRLF().
-----------------------------------------------------------------------
ENTENDENDO A NUMERACAO DOS PIXELS E O METODO :LEFTMARGIN.
Após testes descobri que do inicio do papel até a COLUNA ZERO DE TEXTO, existem O DOBRO de pixels de :LeftMargin.
Exemplo, imprimindo na Cannon G4000, onde oJob:LeftMargin é igual a 80:
Do inicio do papel até o pixel zero temos 80 pixels nao imprimiveis.
Nesse ponto temos o PIXEL ZERO, onde já podemos imprimir ou desenhar algo.
Desse ponto até a COLUNA ZERO DE TEXTO temos mais 80 pixels.
Total de 160 pixels, do inicio do papel até a coluna zero de texto.
Portanto, o primeiro pixel do papel é o -80 que é o valor retornado por :InchToPosX(0).
Por isso :InchToPosX(1) (1 polegada a partir do inicio do papel) retorna 520, pois PPP (pixels por polegada) = 600.
Desenhando seria mais ou menos isso, em relacao ao eixo X (coluna de pixels):
Form A4, na Cannon onde oJob:LeftMargin=80 e oJob:PixelsPerInchX=600 :
_______________________________________________
\ \ \ \
\ \ \ Pixel 520 (600 pixels (1 polegada) de distancia na beira do papel -> :Inch_To_PosX(1)
\ \ \
\ \ Pixel 80 : Coluna 0 de :SetPRC e 80 (obviamente) de :SetPOS
\ \
\ Pixel 0 : primeiro pixel onde é possivel desenhar ou escrever qualquer coisa.
\
Pixel -80 : Inicio do papel
Esse esquema é o mesmo em relação ao eixo Y, as linhas e :TopMargin.
O mesmo se deu com a Brother, que tinha :LeftMargin = 100
Pixels comecam no -100
Pixel a 1 polegada do inicio do papel = 500
Pixel de inicio da coluna 0 de SetPrc = 100
A conclusao baseada nos 2 exemplos é:
Considerando a variavel QLM = :leftMargin
1 - O PAPEL comeca no pixel -QLM (negativo mesmo)
2 - Pixel ZERO (:SetPOS(0,) primeiro pixel X imprimivel) deixa QLM pixels pra trás (os pixels negativos que nao se pode imprimir)
3 - Coluna ZERO (:SetPRC(,0) começa no pixel QLM e deixa 2*QLM pixels pra trás (QLM pixels negativos e QLM pixels positivos)
4 - É possivel imprimir no pixel ZERO com :TextOut mas a coluna ZERO de :SetPRC é o pixel QLM, nao sei porque.
Pode-se considerar que :LeftMargin se refere a diferença entre :SetPOS(0,) e :SetPRC(,0) mas quando usamos os
métodos :Inch_To_PosX() ou :MM_To_PosX() que contam os pixels desde a beira do papel, a conta não fechava e tive que entender
que há pixels NEGATIVOS não imprimíveis pra fechar a conta.
Essas explicações são apenas para efeito de informação. Não influem em nada no funcionamento das funções EP.
--------------------------------------------------------------------------------------------------------------
ENTENDENDO A ALTURA DA LINHA:
(Os dados de exemplos são referentes a impressora Microsoft Print to PDF, em outras impressoras nao sei se estes valores
tem variações.)
Se o tamanho de fonte escolhido for 12 ou menor, não é necessario mudar a altura da linha, que o Harbour por default
define em 100 pixels. A não ser que queira ter mais linhas por pagina.
Se for mudar a altura da linha com a função EP_SetLinha, isso deve ser feito no inicio do Job, logo após a definição da
fonte. SetLinha() regula a altura da linha em caracteres, e por isso, o tamanho de fonte já deve estar definido.
Assim desde o inicio temos uma definicao clara de quantas linhas o relatorio terá, para um melhor entendimento e
posicionamento dos textos ou imagens, independente de titulos ou dados destacados com fontes maiores.
Quando muda-se o tamanho da fonte para impressao de destaque, a altura da linha nao é afetada.
Deve-se controlar isso manualmente, pulando linha se necessario, para que o texto em destaque nao se sobreponha nos
textos imediatamente acima.
Quando um Job é iniciado, o Harbour, por default, define o tamanho 12 (que tem 100 pixels de altura) e a altura da
linha em 100 pixels, o que dá 69 linhas de relatorio A4 na impressora Microsoft Print to PDF.
Se mudarmos a fonte para tamanho 10 (que tem 83 pixels de altura), não é necessario mudar a altura da linha, pois com
uma fonte menor nao haverá sobreposição das linhas.
Porem, se precisarmos de um relatorio ou carta com uma fonte tamanho 13 (108 pixels) ou 14 (117 pixels) é necessario
mudar a altura da linha, ou as linhas vao se sobrepor. Para isso, após definir o tamanho da fonte, use EP_SetLinha(1) para
definir a altura da linha em 1 caractere, i.e., se o tamanho de fonte definido for 14, EP_SetLinha(1) definirá a altura da
linha em 117 pixels.
Nesse caso, o relatorio terá um numero menor de linhas por pagina. Após mudar a altura da linha, use a funcao
EP_MaxRow() para saber quantas linhas por pagina o relatorio terá.
Lembre-se: Se for usar a funcao EP_SetLinha para mudar a altura da linha, faça isso no inicio do job logo após EP_StartJob,
antes de inciar as impressoes, e reposicione para o inicio da pagina com EP_Goto(1,1).
Se mudar a altura da linha no meio do relatorio, nao faço ideia do que terá que fazer pra posicionar perfeito.
Só testando. Nao é aconselhável.
--------------------------------------------------------------------------------------------------------------
ENTENDENDO O AJUSTE FINO DOS DESENHOS DE LINES, BOX E ELIPSES:
Normalmente, o ajuste fino default é suficiente justamente para trabalharmos apenas com linhas (rows) e colunas de texto,
mas se necessário, use o ajuste fino dos desenhos de lines, box e elipses.
Para evitar alguma confusao, nesta explicação linhas DE TEXTO serão referenciadas como ROW.
A palavra LINE significa o desenho de uma linha.
Considerando uma altura de ROW (:LineHeight) de 13 pixels e uma largura de caractere (:CharWidth) de 6 pixels,
abaixo vemos a representacao de uma unica ROW em pixels até a coluna 5.
Ajuste fino da LINE horizontal:
DV = Deslocamento vertical
PI = Ponto de inicio
PF = Ponto final
Neste exemplo, o default seria:
DV=7 (meio da ROW)
PI=1
PF=6
EP_LinhaHorizontal(Row,2,5,DV,PI,PF) daria o seguinte resultado:
(O mesmo que EP_LinhaHorizontal(Row,2,5) já que estamos usando os valores default)
Neste exemplo a LINE é desenhada no meio da ROW, da coluna 2 até a 5, e atravessando totalmente a primeira e ultima coluna.
coluna 1 coluna 2 coluna 3 coluna 4 coluna 5
PI=1 (default) Aqui começa a LINE PF=6 (default) Aqui termina a LINE
/ /
pixel 1 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 2 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 3 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 4 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 5 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 6 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 7 da Row --> _:_:_:_:_:_H############################################### <-- Posicao default da LINE = meio da ROW
pixel 8 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 9 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 10 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 11 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 12 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
pixel 13 da Row --> _:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_H_:_:_:_:_:_
\ \ \ \
\ pixel 6 da coluna \ pixel 6 da coluna
\ \
pixel 1 da coluna pixel 1 da coluna
Ajuste fino da LINE vertical:
DL = Deslocamento lateral
PI = Ponto de inicio
PF = Ponto final
Neste exemplo, o default seria:
DL=3 (meio da coluna)
PI=7 (iniciando no meio da row)
PF=7 (terminando no meio da row)
EP_LinhaVertical(2,10,12,DL,PI,PF) daria o seguinte resultado:
(O mesmo que EP_LinhaVertical(2,10,12) já que estamos usando os valores default)
Neste exemplo a LINE é desenhada no meio da COLUNA, da ROW 10 até a 12, e atravessando apenas metade da primeira e ultima ROW.
coluna 1 coluna 2
pixel 1 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
pixel 2 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
pixel 3 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
pixel 4 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_ ROW 10
pixel 5 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
pixel 6 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
pixel 7 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_ <-- Aqui começa a LINE
pixel 8 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 9 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 10 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 11 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 12 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 13 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
#
pixel 1 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 2 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 3 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 4 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_ ROW 11
pixel 5 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 6 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 7 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 8 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 9 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 10 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 11 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 12 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 13 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
#
pixel 1 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 2 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 3 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 4 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_ ROW 12
pixel 5 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 6 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_
pixel 7 da ROW --> _:_:_:_:_:_H_:_:#:_:_:_ <-- Aqui termina a LINE
pixel 8 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
pixel 9 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
pixel 10 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
pixel 11 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
pixel 12 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
pixel 13 da ROW --> _:_:_:_:_:_H_:_:_:_:_:_
\ \
\ pixel 6 da coluna
\
pixel 1 da coluna
Como foi possível observar, os pontos iniciais e finais default da linha horizontal fazem a LINE atravessar totalmente o
primeiro e ultimo caractere, enquanto que os pontos iniciais e finais default da linha vertical estão no meio do
primeiro e ultimo caractere, respectivamente.
Foi definido assim por ser mais comum usarmos uma LINE horizontal isolada dividindo partes de um relatorio.
Já uma LINE vertical, é mais comum se encontrando com LINES horizontais, divindo boxes, por exemplo.
Mas como obviamente nem sempre é assim, existe o ajuste fino.
Se precisar de ajuste fino para a funcao EP_Box, o procedimento é basicamente o mesmo, porém, só precisa informar os 4
deslocamentos das LINES do Box (verticais e laterais) em um array de 4 elementos.
O ponto inicial e final das LINES, a própria função EP_Box os define para que as LINES se encontrem, fechando o Box.
Além do mais, EP_Box já tem 3 valores padrão (PMG) para estes deslocamentos (Ver explicações na função).
*/
func EP_StartJob
* Inicia job de impressao A4 para a variavel publica oJob
* Param 1 : Nome da impressora
* Param 2 : Margem esquerda em milimetros (default=15mm)
* Param 3 : Margem direita em milimetros (default=15mm)
* Param 4 : Nome do job (opcional)
* Inicia o Job com fonte "Lucida Console", tamanho 12 e 85 colunas.
para cPrinterName,nMargemEsq,nMargemDir,cJobName
* Cria as variaveis publicas necessarias
public oJob,EP_PrimeiroXUtil,EP_PrimeiroYUtil,EP_MEsquerdaMM,EP_MDireitaMM,EP_LarguraPapelMM
public EP_NC, EP_CW, EP_LH // NC=Nr de Colunas / CW=CharWidth / LH=LineHeight
default(@nMargemEsq,15)
default(@nMargemDir,15)
EP_MEsquerdaMM=nMargemEsq
EP_MDireitaMM=nMargemDir
oJob = win_prn():New(cPrinterName)
oJob:FormType:= 9 // A4
oJob:SetPrintQuality(-3) // Informo por informar resolucao media mas nenhuma funciona, nao sei porque.
oJob:Landscape:= .F.
oJob:Copies:= 1
oJob:Create()
oJob:StartDoc(cJobName)
EP_LarguraPapelMM=210 // A4
* Vou considerar a linha 1 iniciando a 5 mm do topo do papel. Menos é pouco usual.
* Mas nada impede de iniciar o relatorio na linha zero, se quiser aproveitar o topo ao maximo.
* Mas não esqueça:
* -> 5 mm será a distancia DO TOPO da linha 1 para o inicio DO PAPEL.
* -> EP_PrimeiroYUtil (primeiro pixel Y do relatorio) é o TOPO da linha 1
* -> O posicionamento em pixel da linha de texto 1 é EP_PrimeiroYUtil + :LineHeight - 1
* (isso é padrão dos métodos :SetPrc e :TextOut. O posicionamento em pixel da linha se dá na base da linha e nao no topo)
*
* Já no eixo X é diferente, pois o posicionamento em pixel se dá no pixel mais a esquerda do caractere.
* Portanto:
* -> EP_MEsquerdaMM será a distancia da lateral esquerda da coluna 1 para o inicio DO PAPEL.
* -> EP_PrimeiroXUtil (primeiro pixel X do relatorio) é a lateral esquerda da coluna 1 .
* -> O posicionamento em pixel da coluna de texto 1 é simplesmente EP_PrimeiroXUtil.
EP_PrimeiroXUtil=oJob:mm_to_posx(EP_MEsquerdaMM)
EP_PrimeiroYUtil=oJob:mm_to_posy(5)
EP_NC=85
EP_SetFont([Lucida Console],12,EP_NC) // Define fonte padrao Lucida Console, PointSize 12, 85 colunas.
EP_Goto(1,1) // Posiciona no inicio logico da impressao do ponto de vista da biblioteca
oJob:SetPen(,6)
return
func EP_SetFont
* Ativa os dados de fonte e nr de colunas para as proximas impressoes.
* Param 1 : Nome da fonte (default=mantem)
* Param 2 : Altura da fonte (Point Size) (default=mantem)
* Param 3 : Nr de Colunas (default=mantem)
*
* O caractere aperta (comprime) quanto maior for o nr de colunas, e alarga quando diminui o nr de colunas.
* Esta funcao nao permite que se defina a largura do caractere em pixels, pois entendo que nao saberiamos exatamente
* qual seria o valor mais apropriado, e dependeriamos de testes.
* Portanto, apenas defina o nr de colunas que voce quer no seu relatorio, e o caractere se adapta.
para NomeFonte,AltFonte,NrColunas
default(@NomeFonte,oJob:FontName)
default(@AltFonte,oJob:FontPointSize)
default(@NrColunas,EP_NC)
EP_NC=NrColunas
private AreaUtilPols,LarguraPapelPols,MargemEsqPols,MargemDirPols,CPP
* Define CPP, que vai definir a largura (width) do caractere.
* Margem esquerda e direita são definidas em EP_StartJob()
LarguraPapelPols=EP_LarguraPapelMM/25.4
MargemEsqPols=EP_MEsquerdaMM/25.4
MargemDirPols=EP_MDireitaMM/25.4
AreaUtilPols=LarguraPapelPols-MargemEsqPols-MargemDirPols
CPP = NrColunas/AreaUtilPols
* Define as caracteristicas da fonte
* No metodo SetFont o terceiro parametro é um array que define o nr de caracteres por polegada (segundo elemento dividido pelo
* primeiro).
* Porem, nao consegui entender essa matematica, pois nesse caso {1,11.5} deveria ser igual a {3,34.5}, mas não é: produz
* resultados diferentes quando o segundo elemento não é inteiro.
* Descobri que o primeiro elemento muito pequeno, como 1, não fica preciso, e melhora a precisao quando voce aumenta.
* Por isso, como não sei quanto teria que aumentar, botei 200 logo. Assim, as margens desejadas em milimetros ficaram
* praticamente perfeitas com qualquer tamanho de fonte e nr de colunas.
* Obs.: Definir :CharWidth diretamente com o terceiro parametro numerico em vez de array, tambem nao funcionou.
* Só funcionou precisamente assim: array com um divisor alto.
oJob:SetFont(NomeFonte, AltFonte, {200,200*CPP} )
* Obs2.: Enviar o segundo elemento do array em negativo força tamanhos iguais para todos os caracteres, mesmo que a fonte
* nao seja de tamanho fixo como Lucida ou Courier, mas não fica lá muito bom, então aqui eu nao vou usar esse recurso,
* e por isso se usar esse tipo de fonte, saiba que as colunas vão ficar desalinhadas.
EP_CW=oJob:CharWidth
EP_LH=oJob:LineHeight
EP_UltimoXUtil=EP_PrimeiroXUtil+(EP_NC*EP_CW)-1
return
func EP_Goto
* Posiciona a impressao na linha e coluna
* Param 1 : Nr da linha (default=mesma linha)
* Param 2 : Nr da coluna (default=margem esquerda)
* Se for usar EP_Say1 após EP_Goto, posicione na linha anterior, já que EP_Say1 imprime na proxima linha.
* Se for usar EP_Say0 após EP_Goto, pode informar a linha e coluna certa que quer posicionar.
* O intervalo logico de posicionamento dentro da area util do relatorio é de 1 a EP_MaxCol() ou EP_MaxRow()
* É possível enviar numeros fora desse intervalo se assim quiser, e o posicionamento ficará fora das margens.
* EP_Goto(,-3) posiciona o inicio antes da margem esquerda, para impressao de uma linha tracejada de corte, por exemplo.
* Tambem é possivel enviar linha ou coluna quebrada para impressao de sobrescrito ou subscrito.
para nlin,ncol
default(@nlin,EP_Prow())
default(@nCol,1)
oJob:SetPos(EP_ColToX(ncol),EP_RowToY(nlin))
return
func EP_CRLF // Carriage Return + Line Feed
* Avanca N linhas
* Param 1 : Quant de linhas a avancar (default=1 Proxima linha)
* Posiciona na margem esquerda.
* Se a linha atual estiver quebrada após alguma impressao de sobrescrito ou subscrito, aqui isso é acertado.
* Por isso, oJob:Newline() não é aconselhavel em nenhum momento pois ele soma :LineHeight ao posicionamento atual,
* e se a linha estiver quebrada vai continuar quebrada.
* Use sempre EP_CRLF() para avancar 1 ou mais linhas.
para nlinhas
default(@nlinhas,1)
EP_Goto(int(EP_Prow())+nlinhas,1)
return
func EP_Negrito
* Liga/Desliga negrito com a intensidade definida no segundo parametro (default=700)
para x,valneg
default(@valneg,700)
oJob:SetFont( , , , if(x,valneg,0) )
return
func EP_Sublinhado
* Liga/Desliga sublinhado
para x
oJob:SetFont( , , , , x )
return
func EP_Italico
* Liga/Desliga italico
para x
oJob:SetFont( , , , , , x )
return
func EP_Prow
* Retorna a EXATA linha atualmente posicionada, COM DECIMAIS se for o caso.
* Curiosamente, apesar de :SetPRC permitir que se posicione em linha e coluna quebrada (com decimais), o método :Prow sempre
* retorna um valor inteiro, i.e., se o posicionamento estiver quebrado, pode-se dizer que o retorno do método é ERRADO.
return EP_YToRow(oJob:PosY)
func EP_Pcol
* Retorna a coluna LOGICA atualmente posicionada, COM DECIMAIS se for o caso.
* Curiosamente, apesar de :SetPRC permitir que se posicione em linha e coluna quebrada (com decimais), o método :Pcol sempre
* retorna um valor inteiro, i.e., se o posicionamento estiver quebrado, pode-se dizer que o retorno do método é ERRADO.
return EP_XToCol(oJob:PosX)
func EP_MaxRow
private PixelsMargemTopo,AlturaUtilPixels
PixelsMargemTopo=oJob:TopMargin+EP_PrimeiroYUtil
AlturaUtilPixels=oJob:PageHeight-(PixelsMargemTopo*2) // vezes 2 é pra dar a mesma margem no topo e embaixo
return round(AlturaUtilPixels/EP_LH,0)
func EP_MaxCol
return EP_NC
func EP_Say1
* Imprime o texto em uma nova linha a partir da coluna 1.
* Param 1 : Texto a imprimir
* Param 2 : T/F para Negrito 700
* Param 3 : T/F para Sublinhado
* Param 4 : T/F para Italico
* Param 5 : T/F para Circundado por uma elipse
* Param 6 : T/F para Riscado
* Para imprimir antes da coluna 1 (nao sei porque voce iria querer fazer isso) use EP_Goto() com um numero de coluna
* menor que 1 para posicionar e EP_Say0 que imprime na mesma linha a partir da posicao atual.
* Se informar negrito/sublinhado/italico é só pra impressao agora. Nao muda a definicao atual.
* Para ligar/desligar definitivo use as funcoes EP_Negrito/Sublinhado/Italico.
* Se nao informar negrito/sublinhado/italico usa a definicao atual.
* Se usar EP_Say1("") voce estará apenas posicionando no inicio da proxima linha (o mesmo que EP_CRLF())
para cTexto,negrito,sublinhado,italico,circundado,riscado
EP_CRLF()
EP_Say0(cTexto,negrito,sublinhado,italico,circundado,riscado)
return
func EP_Say0
* Imprime o texto na mesma linha, a partir da posicao atual.
* Param 1 : Texto a imprimir
* Param 2 : T/F para Negrito 700
* Param 3 : T/F para Sublinhado
* Param 4 : T/F para Italico
* Param 5 : T/F para Circundado por uma elipse
* Param 6 : T/F para Riscado
* Se informar negrito/sublinhado/italico é só pra impressao agora. Nao muda a definicao atual.
* Para ligar/desligar definitivo use as funcoes EP_Negrito/Sublinhado/Italico
* Se nao informar usa a definicao atual.
para cTexto,negrito,sublinhado,italico,circundado,riscado
default(@circundado,.f.)
default(@riscado,.f.)
private n,s,i,nColIni,nColFim,nCol,nPosX
* Guarda estados atuais
n=oJob:bold()
s=oJob:underline()
i=oJob:italic()
if negrito<>nil
oJob:bold(if(negrito,700,0))
endif
if sublinhado<>nil
oJob:underline(sublinhado)
endif
if italico<>nil
oJob:italic(italico)
endif
nCol=ep_pcol() // Guarda a coluna atual (inicio do texto)
nPosX=oJob:PosX
oJob:TextOut(cTexto) // Imprime o texto
* Restaura estados anteriores
oJob:bold(n)
oJob:underline(s)
oJob:italic(i)
if circundado
nColIni=nCol-1
nColFim=ep_xtocol(nPosX+oJob:GetTextWidth(cTexto))
ep_elipse(ep_prow()-0.75,nColIni,ep_prow()+0.75,nColFim)
endif
if riscado
nColIni=nCol
nColFim=ep_xtocol(nPosX+oJob:GetTextWidth(cTexto)-ep_cw)
ep_LinhaHorizontal(ep_prow(),nColIni,nColFim)
endif
return
func EP_Say0C
* Imprime o texto centralizado na linha atual, ou na parte da linha atual informada nos parametros 7 e 8.
* O texto será impresso centralizado mas pode nao ficar alinhado com as colunas do relatorio, pois se o cálculo da
* posição nao der exato, o posicionamento de coluna ficará com decimais.
* Ao mudar de linha com EP_CRLF() ou EP_Say1() isso é corrigido. Ou corrija com EP_Goto() logo após.
*
* Parametros 7 e 8 (numericos) opcionais:
* Colunas inicial e final onde o texto deverá ser centralizado - default=1 e EP_MaxCol() (linha inteira)
*
* Parametro 7 (array) opcional:
* Array de 2 elementos com 2 pixels X entre os quais o texto deverá ficar centralizado.
*
* Se o Parametro 7 for um Array de 2 elementos (pixels), o parametro 8 é ignorado, i.e., se for informar colunas informe os
* parametros 7 e 8 numericos, mas se for informar pixels, informe os 2 em um array no parametro 7.
*
* Se o texto estiver entre 2 linhas verticais voce pode informar no parametro 7, os retornos da funcao EP_LinhaVertical de
* quando as linhas foram desenhadas.
* Se as linhas foram desenhadas pela funcao EP_Box, voce pode informar no parametro 7 o proprio array de retorno da funcao EP_Box.
para texto,negrito,sublinhado,italico,circundado,riscado,p7,p8
default(@p7,1)
default(@p8,EP_NC)
private nPricol,nUltcol,nTamanhoTextoEmPixels,nPixelMinimo,nPixelMaximo,nPixelMedio,nPixelInicio
* Define primeira e ultima coluna onde o texto deverá ser centralizado
if type([p7])=[N]
nPricol=p7
nUltcol=p8
elseif type([p7])=[A]
if p7[1]=NIL
p7[1]=ep_coltox(1)
endif
if p7[2]=NIL
p7[2]=ep_coltox(EP_NC)+EP_CW-1
endif
nPricol=ep_xtocol(p7[1])
nUltcol=ep_xtocol(p7[2]-EP_CW+1)
endif
nTamanhoTextoEmPixels=oJob:GetTextWidth(texto) // Tamanho do texto em pixels
nPixelMinimo=ep_coltox(nPricol)
nPixelMaximo=ep_coltox(nUltcol)+EP_CW-1
nPixelMedio=(nPixelMinimo+nPixelMaximo)/2
* Define pixel inicial de impressao do texto.
nPixelInicio=round(nPixelMedio-(nTamanhoTextoEmPixels/2)+1,0)
oJob:SetPos(nPixelInicio)
EP_Say0(texto,negrito,sublinhado,italico,circundado,riscado)
return
func EP_Say0L
* Imprime o texto alinhado a esquerda na linha atual, iniciando na posicao informada.
* O texto será impresso alinhado a esquerda e pode nao ficar alinhado com as colunas do relatorio, pois se o cálculo da
* posição nao der exato, o posicionamento de coluna ficará com decimais.
* Ao mudar de linha com EP_CRLF() ou EP_Say1() isso é corrigido. Ou corrija com EP_Goto() logo após.
*
* Parametro 7 (numerico) opcional:
* Coluna onde o texto deverá iniciar - default=1 (inicio da linha)
*
* Parametro 7 (array) opcional:
* Array de 1 ou mais elementos cujo primeiro elemento tenha o pixel X onde o texto deverá iniciar com afastamento de 1 caractere.
* (Só o primeiro elemento do array é considerado).
*
* I.e., se for informar coluna informe o parametro 7 numerico. Se for informar pixel, informe um array.
*
* Se o texto deve iniciar em uma linha vertical voce pode informar (em forma de array) no parametro 7, o retorno da
* funcao EP_LinhaVertical de quando a linha foi desenhada. Ex.: EP_Say0L(texto,,,,,,{RetornoDesenhoLinha})
* Ou ainda, se a linha foi desenhada pela funcao EP_Box, voce pode informar no parametro 7 o proprio array de retorno da
* funcao EP_Box, já que a linha esquerda é o primeiro elemento do array.
*
* Obs.: Se a definicao da posicao foi feita por um array (parametro 7), um afastamento de 1 caractere será dado automaticamente.
* Se nao, o texto vai iniciar exatamente na coluna informada, ou na primeira, se nenhuma foi informada.
para texto,negrito,sublinhado,italico,circundado,riscado,p7
default(@p7,1)
private nPricol,nAfast,nPixelMaximo,nTamanhoTextoEmPixels,nPixelInicio
nAfast=1 // Afastamento automatico em caracteres para caso a definicao do espaco tenha vindo em um array de pixels
* Como a biblioteca trabalha mais com linhas e colunas de texto, vou definir primeiro coluna inicial do texto
if type([p7])=[N]
nPricol=p7
elseif type([p7])=[A]
nPricol=ep_xtocol(p7[1]+(EP_CW*nAfast))
endif
EP_Goto(,nPricol)
EP_Say0(texto,negrito,sublinhado,italico,circundado,riscado)
return
func EP_Say0R
* Imprime o texto alinhado a direita na linha atual, terminando na posicao informada.
* O texto será impresso alinhado a direita e pode nao ficar alinhado com as colunas do relatorio, pois se o cálculo da
* posição nao der exato, o posicionamento de coluna ficará com decimais.
* Ao mudar de linha com EP_CRLF() ou EP_Say1() isso é corrigido. Ou corrija com EP_Goto() logo após.
*
* Parametro 7 (numerico) opcional:
* Coluna onde o texto deverá terminar - default=EP_MaxCol() (final da linha)
*
* Parametro 7 (array) opcional:
* Array de 1 ou mais elementos cujo ultimo elemento tenha o pixel X onde o texto deverá terminar com afastamento de 1 caractere.
* (Só o ultimo elemento do array é considerado).
*
* I.e., se for informar coluna informe o parametro 7 numerico. Se for informar pixel, informe um array.
*
* Se o texto deve terminar em uma linha vertical voce pode informar (em forma de array) no parametro 7, o retorno da
* funcao EP_LinhaVertical de quando a linha foi desenhada. Ex.: EP_Say0R(texto,,,,,,{RetornoDesenhoLinha})
* Ou ainda, se a linha foi desenhada pela funcao EP_Box, voce pode informar no parametro 7 o proprio array de retorno da
* funcao EP_Box, já que a linha direita é o ultimo elemento do array.
*
* Obs.: Se a definicao da posicao foi feita por um array (parametro 7), um afastamento de 1 caractere será dado automaticamente.
* Se nao, o texto vai terminar exatamente na coluna informada, ou na ultima, se nenhuma foi informada.
para texto,negrito,sublinhado,italico,circundado,riscado,p7
default(@p7,EP_NC)
private nUltcol,nAfast,nPixelMaximo,nTamanhoTextoEmPixels,nPixelInicio
nAfast=1 // Afastamento automatico em caracteres para caso a definicao do espaco tenha vindo em um array de pixels
* Como a biblioteca trabalha mais com linhas e colunas de texto, vou definir primeiro coluna final do texto
if type([p7])=[N]
nUltcol=p7
elseif type([p7])=[A]
nUltcol=ep_xtocol(p7[len(p7)]-EP_CW+1-(EP_CW*nAfast))
endif
* Já tendo a ultima coluna, define ultimo pixel limite, porque devido a diferenca de pixels entre fontes nao-fixas,
* o posicionamento final será em pixel (PosX).
nPixelMaximo=ep_coltox(nUltcol)+EP_CW-1
nTamanhoTextoEmPixels=oJob:GetTextWidth(texto) // Tamanho do texto em pixels
* Define pixel inicial de impressao do texto.
nPixelInicio=nPixelMaximo-nTamanhoTextoEmPixels+1
oJob:SetPos(nPixelInicio)
EP_Say0(texto,negrito,sublinhado,italico,circundado,riscado)
return
func EP_EndJob
EP_Elipse()
oJob:EndDoc()
oJob:Destroy()
release oJob,EP_PrimeiroXUtil,EP_UltimoXUtil,EP_PrimeiroYUtil,EP_MEsquerdaMM,EP_MDireitaMM,EP_LarguraPapelMM
release EP_NC, EP_CW, EP_LH
return
func EP_Eject
EP_Elipse()
oJob:NewPage()
EP_Goto(1,1)
return
func EP_SetLinha
* Define a altura da linha em caracteres.
* Isto é, se definir altura da linha igual a 1, a linha terá a altura de 1 caractere.
* Parametro : Altura da linha (default=1)
* Altura da linha = 1 as linhas ficam normais sem espacamento.
* Altura = 1.5 a linha fica com 50% a mais que a altura da fonte (Visualmente, é como pular meia linha)
* Altura = 2 a linha fica com o dobro da altura da fonte (Visualmente, é como pular 1 linha)
* Altura = 3 a linha fica 3x maior que a altura da fonte (Visualmente, é como pular 2 linhas)
para altura
default(@altura,1)
oJob:LineHeight=round(altura*oJob:CharHeight(),0)
EP_LH=oJob:LineHeight
return
func EP_PrintImage
* Imprime o arquivo de imagem informado para o objeto oJob.
* Parametro 1 : nome do arquivo com extensao
* Parametro 2 e 3 : Coordenadas (linha e coluna) do canto superior esquerdo (default posicao atual)
* Parametro 4 e 5 : Coordenadas (linha e coluna) do canto inferior direito.
* Linha e coluna se referem a linha e coluna de texto, e nao pixels.
* Pode ser informado valores quebrados para linha e coluna, para ajuste fino da posicao de inicio ou tamanho da imagem.
* Se nao informar uma das 2 coordenadas de final da imagem (parametro 4 e 5), a imagem manterá a proporção original.
* Se nao informar nenhuma das 2, a imagem é impressa no tamanho original.
para nomearq,lin,col,lin2,col2
default(@lin,EP_Prow())
default(@col,EP_Pcol())
private oImg,nHeight,nWidth,PercLargura,PercAltura,PixelX,PixelY,largura,altura
oImg := win_oleCreateObject( "WIA.ImageFile" )
oImg:LoadFile(nomearq)
nWidth := oImg:Width
nHeight := oImg:Height
PercLargura = nWidth/nHeight*100
PercAltura = nHeight/nWidth*100
* Define largura e altura da imagem em pixels.
* Se nao informou nem linha nem coluna final, assume o original da imagem (já em pixels)
if lin2=NIL .and. col2=NIL
largura=nWidth
altura=nHeight
* Se nao informou coluna final, define largura na proporcao original
elseif col2=NIL
altura=(lin2-lin+1)*EP_LH
largura=p(PercLargura,altura)
* Se nao informou linha final, define altura na proporcao original
elseif lin2=NIL
largura=(col2-col+1)*EP_CW
altura=p(PercAltura,largura)
else
largura=(col2-col+1)*EP_CW
altura=(lin2-lin+1)*EP_LH
endif
* Transforma linha e coluna de inicio para pixels.
PixelX=EP_ColToX(col)
PixelY=EP_RowToY(lin)-oJob:LineHeight+1 // Posiciona a imagem no topo da linha de inicio e nao na base
oImg=win32bmp():new()
oImg:LoadFile(nomearq)
oImg:draw( oJob , { PixelX, PixelY, largura , altura } )
return
func EP_LinhaHorizontal // ( L , C1 , C2 )
* Desenha uma linha horizontal divisora na linha L da coluna C1 a C2
* Retorna o nr do pixel Y onde a linha foi desenhada.
*
* Parametro 1 = Linha (Row()) onde será desenhada a linha (default=atual)
* Parametro 2 = Coluna inicial
* Parametro 3 = Coluna final
* Parametro 4 = Deslocamento vertical da linha em pixels
* Valores aceitos : de 1 a altura da linha (default=meio da linha)
* Parametro 5 = Ponto de inicio da linha
* Valores aceitos : de 1 a largura do caractere (default=1)
* Parametro 6 = Ponto de final da linha
* Valores aceitos : de 1 a largura do caractere (default=largura do caractere)
* Os valores default dos parametros 5 e 6 da linha horizontal sao para que a linha atravesse inteiramente o primeiro e
* ultimo caractere, já que é comum usarmos uma linha horizontal isolada dividindo partes do relatorio.
* Já os valores default da linha vertical iniciam e terminam no meio da row, pois é mais comum linhas verticais se
* encontrando com as horizontais, divindo boxes, por exemplo.
para L,C1,C2,pv,pi,pf
default(@L,EP_Prow())
default(@pv,int(oJob:LineHeight/2))
default(@pi,1)
default(@pf,oJob:CharWidth)
* Corrige erros nos parametros
pv=if(pv<1,1,pv)
pv=if(pv>oJob:LineHeight,oJob:LineHeight,pv)
pi=if(pi<1,1,pi)
pi=if(pi>oJob:CharWidth,oJob:CharWidth,pi)
pf=if(pf<1,1,pf)
pf=if(pf>oJob:CharWidth,oJob:CharWidth,pf)
* Transforma a linha em pixels e posiciona no ultimo pixel da linha anterior para aguardar o
* acrescimo do ajuste fino.
L=EP_RowToY(L)-oJob:LineHeight
* Transforma a coluna em pixels e posiciona no final da coluna anterior para aguardar o
* acrescimo do ajuste fino.
C1=EP_ColToX(C1)-1
C2=EP_ColToX(C2)-1
* Soma o ajuste fino solicitado chegando a posical final
L+=pv
C1+=pi
C2+=pf
ojob:line(C1,L,C2,L)
return L
func EP_LinhaVertical // ( C , L1 , L2 )
* Desenha uma linha vertical divisora na coluna C (default=atual) da linha L1 a L2
* Retorna o nr do pixel X onde a linha foi desenhada.
*
* Parametro 1 = Coluna onde será desenhada a linha (default=atual)
* Parametro 2 = Linha inicial
* Parametro 3 = Linha final
* Parametro 4 = Deslocamento lateral da linha em pixels
* Valores aceitos : de 1 a largura do caractere (default=meio da coluna)
* Parametro 5 = Ponto de inicio da linha
* Valores aceitos : de 1 a altura da linha (EP_LH) (default=meio da linha)
* Parametro 6 = Ponto final da linha
* Valores aceitos : de 1 a altura da linha (EP_LH) (default=meio da linha)
* Os valores default dos parametros 5 e 6 da linha horizontal sao para que a linha atravesse inteiramente o primeiro e
* ultimo caractere, já que é comum usarmos uma linha horizontal isolada dividindo partes do relatorio.
* Já os valores default da linha vertical iniciam e terminam no meio da row, pois é mais comum linhas verticais se
* encontrando com as horizontais, divindo boxes, por exemplo.
para C,L1,L2,ph,pi,pf
default(@C,EP_Pcol())
default(@ph,int(oJob:CharWidth/2))
default(@pi,int(oJob:LineHeight/2))
default(@pf,int(oJob:LineHeight/2))
* Corrige erros nos parametros
ph=if(ph<1,1,ph)
ph=if(ph>oJob:CharWidth,oJob:CharWidth,ph)
pi=if(pi<1,1,pi)
pi=if(pi>oJob:LineHeight,oJob:LineHeight,pi)
pf=if(pf<1,1,pf)
pf=if(pf>oJob:LineHeight,oJob:LineHeight,pf)
* Transforma a coluna em pixels e posiciona no final da coluna anterior
C=EP_ColToX(C)-1
* Transforma a linha em pixels e posiciona no final da linha anterior
L1=EP_RowToY(L1)-oJob:LineHeight
L2=EP_RowToY(L2)-oJob:LineHeight
* Soma o ajuste fino chegando a posical final
C+=ph
L1+=pi
L2+=pf
ojob:line(C,L1,C,L2)
return C
func EP_Box // ( L1, C1 , L2 , C2 , P )
* Desenha um box nas coordenadas informadas
* Retorna array de 2 elementos com os nrs dos pixels X das linhas verticais esquerda e direita.
*
* Parametro 5 : Numerico: 1, 2, ou 3 (PMG)
* 1 = P = Menor tamanho - No limite interno da linha ou coluna,
* 2 = M = Tamanho medio - Pelo meio da linha ou coluna (default)
* 3 = G = Maior tamanho - No limite externo da linha ou coluna
*
* Parametro 5 : Array de 4 elementos com o ajuste fino do box dentro da linha ou coluna.
* Se quiser um ajuste fino do posicionamento envie um array com 4 deslocamentos finos dentro da linha ou coluna.
* Valor zero para o elemento, assume centralizado (meio da linha ou coluna)
* Elemento 1 = Topo (de 1 a EP_LH)
* Elemento 2 = Lateral esquerda (de 1 a EP_CW)
* Elemento 3 = Base (de 1 a EP_LH)
* Elemento 4 = Lateral direita (de 1 a EP_CW)
para L1,C1,L2,C2,Param5
private aFinos[4],pxe,pxd
if Param5=NIL
aFinos={int(oJob:LineHeight/2),int(oJob:CharWidth/2),int(oJob:LineHeight/2),int(oJob:CharWidth/2)}
elseif type([Param5])=[N]
if Param5=1
aFinos={oJob:LineHeight,oJob:CharWidth,1,1}
elseif Param5=3
aFinos={1,1,oJob:LineHeight,oJob:CharWidth}
else
aFinos={int(oJob:LineHeight/2),int(oJob:CharWidth/2),int(oJob:LineHeight/2),int(oJob:CharWidth/2)}
endif
else
aFinos=Param5
endif
aFinos[1]=if(aFinos[1]=0,int(oJob:LineHeight/2),aFinos[1])
aFinos[2]=if(aFinos[2]=0,int(oJob:CharWidth/2) ,aFinos[2])
aFinos[3]=if(aFinos[3]=0,int(oJob:LineHeight/2),aFinos[3])
aFinos[4]=if(aFinos[4]=0,int(oJob:CharWidth/2) ,aFinos[4])
EP_LinhaHorizontal( L1,C1,C2, aFinos[1], aFinos[2], aFinos[4] ) // Desenha linha topo
pxe=EP_LinhaVertical( C1,L1,L2, aFinos[2], aFinos[1], aFinos[3] ) // Desenha lateral esquerda
EP_LinhaHorizontal( L2,C1,C2, aFinos[3], aFinos[2], aFinos[4] ) // Desenha linha base
pxd=EP_LinhaVertical( C2,L1,L2, aFinos[4], aFinos[1], aFinos[3] ) // Desenha lateral direita
return {pxe,pxd}
func EP_Elipse
* Desenha uma elipse dentro das coordenadas informadas.
* Retorna array de 2 elementos com os nrs dos pixels X mais a esquerda e mais a direita.
*
* Parametro 5 : Numerico: 1, 2, ou 3 (PMG)
* 1 = P = Menor tamanho - No limite interno da linha ou coluna,
* 2 = M = Tamanho medio - Pelo meio da linha ou coluna (default)
* 3 = G = Maior tamanho - No limite externo da linha ou coluna
*
* Parametro 5 : Array de 4 elementos com o ajuste fino da elipse dentro da linha ou coluna. (default = limite medio)
* Se quiser um ajuste fino do posicionamento envie um array com 4 deslocamentos finos dentro da linha ou coluna.
* Valor zero para o elemento, assume limite medio.
* Elemento 1 = Topo (de 1 a EP_LH) default=EP_LH/2
* Elemento 2 = Lateral esquerda (de 1 a EP_CW) default=EP_CW/2
* Elemento 3 = Base (de 1 a EP_LH) default=EP_LH/2
* Elemento 4 = Lateral direita (de 1 a EP_CW) default=EP_CW/2
*
* EP_Elipse usa um recurso de impressao posterior para que fique sempre por cima dos caracteres que estejam no seu caminho.
* Todas as impressoes pendentes de EP_Elipse serão efetivadas ao trocar de pagina com EP_Eject ou no final com EP_EndJob.
* Se quiser efetivar a impressao antes disso, use EP_Elipse sem parametros.
para L1,C1,L2,C2,Param5
static nElipseCounter:=0
static aElipseXY[100,4]
private aFinos[4],x1,y1,x2,y2,i
* Efetiva elipses pendentes
if pcount()=0
for i=1 to nElipseCounter
x1=aElipseXY[i,1]
y1=aElipseXY[i,2]
x2=aElipseXY[i,3]
y2=aElipseXY[i,4]
oJob:arc(x1,y1,x2,y2)
next
nElipseCounter=0
return
endif
if Param5=NIL
aFinos={int(EP_LH/2),int(EP_CW/2),int(EP_LH/2),int(EP_CW/2)}
elseif type([Param5])=[N]
if Param5=1
aFinos={EP_LH,EP_CW,1,1}
elseif Param5=3
aFinos={1,1,EP_LH,EP_CW}
else
aFinos={int(EP_LH/2),int(EP_CW/2),int(EP_LH/2),int(EP_CW/2)}
endif
else
aFinos=Param5
endif
aFinos[1]=if(aFinos[1]=0,int(EP_LH/2),aFinos[1])
aFinos[2]=if(aFinos[2]=0,int(EP_CW/2),aFinos[2])
aFinos[3]=if(aFinos[3]=0,int(EP_LH/2),aFinos[3])
aFinos[4]=if(aFinos[4]=0,int(EP_CW/2),aFinos[4])
* Transforma as linhas em pixels Y e posicina no final da linha anterior
y1=ep_rowtoy(L1)-EP_LH
y2=ep_rowtoy(L2)-EP_LH
* Transforma as colunas em pixels X e posicina no final da coluna anterior
x1=ep_coltox(C1)-1
x2=ep_coltox(C2)-1
* Soma o ajuste fino chegando a posical final
x1+=aFinos[2]
y1+=aFinos[1]
x2+=aFinos[4]
y2+=aFinos[3]
* Memoriza a posicao da elipse para posterior impressao
nElipseCounter++
aElipseXY[nElipseCounter,1]=x1
aElipseXY[nElipseCounter,2]=y1
aElipseXY[nElipseCounter,3]=x2
aElipseXY[nElipseCounter,4]=y2
return {x1,x2}
func EP_Circle
* Desenha um circulo com centro na linha e coluna atual.
* Parametro 1 numerico : Diametro em nr de linhas
* Parametro 2 numerico : Diametro em nr de colunas
* Informe apenas 1 dos 2 parametros. Se informar os 2, só o parametro 1 será considerado.
* Para ajuste fino da posicao central do circulo, voce pode posicionar com EP_Goto() usando valores quebrados.
* Para ajuste fino do diametro voce pode informar valores quebrados no parametro passado.
para d1,d2
private dp // diametro em pixels
private x1,y1,x2,y2
if d1=NIL
dp=d2*ep_cw
else
dp=d1*ep_lh
endif
x1=int(oJob:PosX+(ep_cw/2)-(dp/2))
y1=int(oJob:PosY-(ep_lh/2)-(dp/2))
x2=int(oJob:PosX+(ep_cw/2)+(dp/2))
y2=int(oJob:PosY-(ep_lh/2)+(dp/2))
oJob:arc(x1,y1,x2,y2)
return {x1,x2}
func EP_XToCol
* Converte pixel X em nr de coluna logica.
* Aqui será como nos métodos da classe: o pixel posicionado da coluna é o primeiro a esquerda (onde o caractere começa).
para px
return ((px-EP_PrimeiroXUtil)/ep_cw)+1
func EP_ColToX
* Converte coluna logica em pixel X
* Aqui será como nos métodos da classe: o pixel posicionado da coluna é o primeiro a esquerda (onde o caractere começa).
para col
return ((col-1)*ep_cw)+EP_PrimeiroXUtil
func EP_YToRow
* Converte pixel Y em nr de linha
* Aqui será como nos métodos da classe: o pixel posicionado da linha é o ultimo embaixo (a "base" da row).
para py
return (py-EP_PrimeiroYUtil+1)/ep_lh
func EP_RowToY
* Converte linha em pixel Y
* Aqui será como nos métodos da classe: o pixel posicionado da linha é o ultimo embaixo (a "base" da row).
para lin
return EP_PrimeiroYUtil+(lin*ep_lh)-1