Enviar strings para impressora

1. Enviar strings para impressora

ian cléver sales fernandes
ianclever

(usa Arch Linux)

Enviado em 12/06/2014 - 01:45h

Pessoal, surgiu a necessidade de criar um programa que imprima caracteres, só que ao invés de ser na tela agora é em impressora de verdade, eu quero saber se alguém conhece alguma maneira em c padrão que seja viável para realizar isso sem precisar trabalhar em nível muito baixo, e que seja portável entre GNU/Linux e windows?
Caso seja, por favor de uma ajudinha aqui, pq se não for viável eu vou ter que caçar uma linguagem de nivel mais alto para trabalhar com mais facilidade com isso.


  


2. Re: Enviar strings para impressora

Luis R. C. Silva
luisrcs

(usa Linux Mint)

Enviado em 12/06/2014 - 10:22h

Pra isso, tem que usar o driver da impressora. Não sei como fazer, mas sei que todo programa deve acessar o driver de impressão e este enviar o arquivo para impressora. Tente pesquisar isso.


3. Re: Enviar strings para impressora

Paulo
paulo1205

(usa Ubuntu)

Enviado em 12/06/2014 - 13:24h

O que você precisa enviar para a impressora? Só texto? Comandos específicos do seu modelo de impressora?

O que você chama de baixo nível? Chamar fopen() em “/dev{,/usb}/lp*” (Linux), “/dev/{,u}lp[nt]*” (BSD) ou “LPT*:” (Windows), e depois escrever no ponteiro recebido com fprintf() ou fputc() é alto nível ou baixo nível para você (considerando que pode necessitar de privilégios especiais)?

Os diferentes sistemas têm diferentes mecanismos de alto nível para impressoras. No mundo UNIX, geralmente o CUPS lhe permitiria montar uma página (ou mesmo um documento inteiro, com várias páginas) em texto puro, em Postscript ou em PDF, encarregando-se de traduzir esse formato para um que a impressora consiga entender. No Windows havia, se não me engano, uma camada que permitia tratar uma página impressa como um elemento da GDI (i.e., semelhante a uma janela, permitindo colocar textos, imagens, ícones etc.). No mundo UNIX, o Xprint/Xprt foi uma tentativa de fazer algo no mesmo sentido, mas acho que nunca vingou.

Se você quiser algo de alto nível mesmo e que seja portável para diferentes sistemas, minha sugestão é usar bibliotecas especializadas ou que ofereçam essa funcionalidade como parte dos recursos que a compõem. No Qt, por exemplo, há uma classe QPrinter e outras classes relacionadas. No mundo GTK+/GNOME, a biblioteca que transforma descrições de desenhos em impressões é a Cairo.


4. Re: Enviar strings para impressora

Luis R. C. Silva
luisrcs

(usa Linux Mint)

Enviado em 13/06/2014 - 09:03h

paulo1205 escreveu:

O que você precisa enviar para a impressora? Só texto? Comandos específicos do seu modelo de impressora?

O que você chama de baixo nível? Chamar fopen() em “/dev{,/usb}/lp*” (Linux) “/dev/{,u}lp[nt]*” (BSD) ou “LPT*:” (Windows), e depois escrever no ponteiro recebido com fprintf() ou fputc() é alto nível ou baixo nível para você (considerando que pode necessitar de privilégios especiais)?

Os diferentes sistemas têm diferentes mecanismos de alto nível para impressoras. No mundo UNIX, geralmente o CUPS lhe permitiria montar uma página (ou mesmo um documento inteiro, com várias páginas) texto puro, em Postscript ou em PDF, encarregando-se de traduzir esse formato para um que a impressora consiga entender. No Windows havia, se não me engano, uma camada que permitia tratar uma página impressa como um elemento da GDI (i.e., semelhante a uma janela, permitindo colocar textos, imagens, ícones etc.). No mundo UNIX, o Xprint/Xprt foi uma tentativa de fazer algo no mesmo sentido, mas acho que nunca vingou.

Se você quiser algo de alto nível mesmo e que seja portável para diferentes sistemas, minha sugestão é usar bibliotecas especializadas ou que ofereçam essa funcionalidade como parte dos recursos que a compõem. No Qt, por exemplo, há uma classe QPrinter e outras classes relacionadas. No mundo GTK+/GNOME, a biblioteca que transforma descrições de desenhos em impressões é a Cairo.


Entendi que baixo nível significa o que é: assembly, máquina...


5. Re: Enviar strings para impressora

ian cléver sales fernandes
ianclever

(usa Arch Linux)

Enviado em 13/06/2014 - 19:12h

bem, desculpe a demora deixa eu explicar melhor, bem eu trabalho em uma empresa se software web, e geralmente quando precisamos de criar algum documento mais específico para cada empresa geramos em formato pdf, via php com fpdf ou criamos em html e deixamos o navegador cuidar do resto, o problema é que agora surgiu um problema lá que a gente precisa imprimir certas informações em pontos exatos de um modelo de notas fiscais que usam obrigatoriamente formulários contínuos que só são reconhecidos em impressoras matriciais, e o pdf infelizmente não se mostrou tão universal nessas impressoras, saiu do rumo completamente.
Pesquisando por aí a fora para tentar achar uma solução web viável, na grande maioria dos sites que passei, nenhuma das alternativas web convecionais funcionaram bem com matriciais, os locais que conseguiram solução foi criando programas em linguaguens não web e rodando esta aplicação no cliente, daí tem soluções em java, em delphi, só que como eu não tenho muito conhecimento com essas linguagem(e também pq gosto mais de c) resolvi procurar uma alternativa na linguagem que eu gosto de usar.

Em buscas por aí, eu encontrei os referidos

sobre /dev/lp0 .. LPT, porém eles gerenciam somente impressoras matriciais que utilizam a porta paralela, mas existem alguns modelos que usam usb(a nossa matricial de teste é USB), algumas usam rede ....

em fim notei que pelo modo padrão eu teria que fazer inúmeras gambiarras para reconhecer as quem é quem (caso tenha mais de 1)....

até aqui não é baixo nível mesmo não, seria tranquilo.

continuei minha busca e as outra alternativas que achei foram tutoriais que me ensinavam a comunicar a nivel de bits, etc com a propria porta paralela e usb ... coisa que é mais interessante para quem está desenvolvendo driver.

o que eu precisaria era me comunicar com o driver(ou gerenciador) e ler o que ele já apurou para mim, e mandar as informações em texto para ele se virar e processar.

ou seja a proposta é mandar um arquivo com texto para o driver(ou gerenciador de impressoras) e ele se virar para mandar imprimir. e também ler informações de quais impressoras existem, qual é padrão, nome ... (em fim fazer uma lista com todas as impressoras conectadas para o sujeito escolher qual ele quer usar para imprimir e também ver se não deu problema na impressão ... coisas que o driver já fornece).

Alguma idéia de como fazer isso de forma não muito sofrida?


6. Re: Enviar strings para impressora

Paulo
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/lpN”, para impressoras ligadas por USB, ou “/dev/lpN”, para as de porta paralela; no BSD, as USB têm nomes “/dev/ulptN” e as paralelas se encontram em “/dev/lptN”. 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 “LPTN:”) 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);



7. Re: Enviar strings para impressora

ian cléver sales fernandes
ianclever

(usa Arch Linux)

Enviado em 18/06/2014 - 01:18h

achei o jeito, aqui, lá no windows é com abrindo o arquivo LPT1, só que com um porém, como a usb foi inventada depois que a micro$oft adotou o windows, não existe nenhum comando nativo de terminal que gerencie isso, daí a solução é compartilhar a impressora na rede(mesmo que não seja uma impressora de rede, de fato), e redireciona a porta dela para uma LPT virtual, daí, não precisa nem gerar para mandar o driver processar é so escrever direto para a impressora, e modestia parte, é bastante rápida a resposta.

o comando lá foi esse:
NET USE LPT1: \\[Nome do computador]\Printer /PERSISTENT: YES

e para GNU/Linux, é o que você já havia falado, escrever para /dev/lpx , sem complicação.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts