paulo1205
(usa Ubuntu)
Enviado em 15/06/2014 - 19:27h
Eu nunca fiz programas para imprimir notas fiscais em matriciais, mas cansei de fazer programas para imprimir em formulários de etiquetas, incluindo gráficos. Cheguei até a fazer um programa com interface gráfica rudimentar em DOS para que alguém pudesse desenhar os bitmaps e convertê-los em arrays que poderiam ser importados para dentro de um programa em C. Isso lá por volta de 1989 a 1994.
A última vez em que eu mexi pessoalmente com impressoras matriciais foi por essa época, com DOS e Windows 3.11 for Workgroups. Eu ACHO que o driver do Windows tinha uma opção de configuração para trabalhar com formulários contínuos, e sei que ALGUNS modelos de impressora matrciais, principalmente as da EPSON (das séries LX e LQ) e compatíveis, tinham uma funcionalidade de, por hardware, posicionar o papel para ser cortado (útil para destacar uma nota fiscal recém-impressa) e depois voltar o papel para o começo de uma nova página.
Eu também ACHO que os programas daquela época não imprimiam através de qualquer driver do Windows. Muitas aplicações ainda eram em DOS com DBASE-III ou Clipper, e o que era em Windows costumava ter livre acesso ao hardware, já que o Windows naquela época era só uma camada fina em cima do DOS. Em outras palavras, praticamente todo o cuidado com posicionar elementos na nota fiscal, trocar largura de fontes, mudar espaçamento de linhas, imprimir pequenos logotipos não-texto, entre outros, ficava dentro da aplicação, com interferência mínima (ou nula) do SO. E como geralmente a aplicação geradora de notas fiscais ficava no computador ligado à impressora e este só tinha conectado a si a impressora de NFs, raramente era necessário apontar em qual porta a aplicação de NFs deveria imprimir.
OK, mas isso é passado! Ou será que não?!
Entendo que você vai necessariamente usar impressoras matriciais com formulários contínuos em que cada folha tem um comprimento fixo. Isso, de cara, restringe bastante o escopo da solução, que já não precisa mais ser absolutamente genérica em todos os aspectos. Você está pensando em ter executáveis nativos para imprimir suas NFs, também não está sendo genérico: os executáveis de Windows certamente vão identificar as possíveis impressoras ou filas de impressão de um jeito, e os executáveis de Linux (se é que vão existir) de outro jeito,
a não ser que você embuta no seu programa o peso de alguma biblioteca que crie um modelo de abstração para seleção e controle de impressoras .
No Linux ou no BSD é fácil descobrir possíveis impressoras fisicamente conectadas, especialmente se o forem através de USB: basta, no caso do Linux, procurar por aqruivos na forma “/dev/usb/lp
N ”, para impressoras ligadas por USB, ou “/dev/lp
N ”, para as de porta paralela; no BSD, as USB têm nomes “/dev/ulpt
N ” e as paralelas se encontram em “/dev/lpt
N ”. Se você quiser fazê-lo através do CUPS, pode usar os comandos
lpstat -a ou
lpc status [all] . Dentro de um programa em C que embuta a biblioteca do CUPS, você poderia usar a API do CUPS, começando com
cupsGetDests ().
Eu não programo em Windows, mas uma rápida googlada mostrou que existe uma função
EnumPrinters (), que você pode chamar a partir do C++, bem como formas de conseguir a mesma informação via linha de comando (ver «http://superuser.com/questions/135393/list-printers-from-command-line-to-text-file
»).
Se você vai imprimir apenas texto puro com espaçamento padrão entre linhas e entre os caracteres da mesma linha ou se vai precisar de uns poucos recursos da ESC/P (a linguagem de comandos de impressoras matriciais da EPSON e compatíveis), eu acho que você vai ter MENOS trabalho se tentar imprimir diretamente do que se tentar montar uma página em Postscript ou PDF para depois submetê-la ao driver de impressão. Acho também que a responsabilidade de enviar a impressão para a impressora ou fila de impressão correta é do usuário, não sua.
A sua aplicação poderia exigir que o administrador Windows associasse uma porta fixa virtual (do tipo “LPT
N :”) no momento da instalação, e essa porta poderia ser local ou através da rede, numa fila de com um tipo de impressora “dumb” (i.e. um driver que não interfira no conteúdo enviado). No mundo UNIX com CUPS, a fila de impressão poderia ser do tipo
raw . Em ambos os casos, a aplicação de impressão poderia ler de um arquivo de configuração, gerado no momento da instalação, em qual porta ou fila de impressão devria escrever. Com isso, seu programa de impressão poderia ser um só e se parecer com isto.
char *prn_path;
FILE *prn_fp;
#ifndef _WINDOWS
char cmd_line[4096];
#endif
read_config_file(NOME_ARQ_CONFIG, &prn_path);
#ifdef _WINDOWS
/*
No Windows, suponho que a impressão deve ser enviada para o dispositivo
LPTn:, que pode ser físico ou um mapeamento de uma fila local (no caso de
impressoaras USB) ou de rede, desde que tais filas usem impressoras de um
tipo que não tente capturar e interferir sobre o conteúdo enviado.
Note no fopen() abaixo o uso do argumento "wb". Necessário para compati-
bilidade com UNIX, que, ao contrário do Windows, não faz distinção entre
arquivos de texto e binários, logo não converte automaticamente "\n" para
"\r\n". A consequência é que será necessário enviar explicitamente a se-
quência "\r\n" se quando se quiser que a impressora pule uma linha.
*/
prn_fp=fopen(prn_path, "wb");
#else
/*
No Linux, suponho uso de CUPS com uma fila do tipo raw/raw queue. A quebra
de linha se faz com "\r\n", e não apenas com "\n".
*/
snprintf(cmd_line, sizeof cmd_line, "lpr -P%s", prn_path);
prn_fp=popen(cmd_line, "w");
#endif
/* Começa enviando o comando ESC/P para reset da impressora. */
fprintf(prn_fp, "\33@");
/*
Posiciona a cabeca de impressão na quinta linha (i.e. pula quatro linhas),
décima coluna (nove espaços em branco), e imprime o texto dessa linha.
*/
fprintf("\r\n\n\n\n %s\r\n", nome_cliente);
/* Imprime tudo o que tem de imprimir. */
fprintf("blablabla\r\nblebleble\r\n..."); /* ... */
/* Finaliza, pulando para o começo da nova página. */
fputc('\f', prn_fp);
fclose(prn_fp);