Jump to content


Photo

Impresion PRELIMINAR a JPG y/o PDF


  • Please log in to reply
5 replies to this topic

#1 pcicom

pcicom

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 267 posts
  • LocationMéxico

Posted 13 April 2017 - 09:16 AM

Saludos CHAVOS..  jejeje
 
Tengo una aplicacion funcionando desde hace mucho tiempo, pero quiero depurarla de tal modo que corrija un pequeño defecto que tiene, es editor de formatos de documentos el cual utilizo para imprimir documentos mediante un archivo .FTO que es modifcable.
 
Explico.
 
Cuando mando la impresion de mi documento a Impresora todo funciona perfectamente y las coordenadas de los datos se imprimen en la posicion correcta en CENTIMTEROS.MILIMETROS donde yo indique
utilizando la funcion descrita aqui abajo para tomar un nFx, nFy, como factores de calculo/aproximacion a las coordenadas donde yo imprimo.  Hasta aqui todo bien sin broncas.
 
En problema esta en cuando quiero hacer un preview imprimiendo en el canvas de una imagen, ahi es donde hay un pequeño error de calculo al imprimir, no se si sea por los pixeles por pulgada y/o algo no estoy generando bien, para lo cual agredecere en caso de que alguien tenga algo similar, y/o el metodo de impresion en canvas a imagen como preview de impresion.
 
 
El previev lo utilizo para:
* Tener vistas previas de los FORMATOS cuando los estoy creando.
* Generar un PDF por medio de los componentes PowerPDF, insertando la imagen. (Sin dependencia de impresoras virtuales y DLL ni nada de nada puro DELPHI).
 
Se que se puede hacer por medio de SynPDF, pero por ahora quisiera solo la aproximacion mas exacta en una IMAGEN.

PROBLEMA.ACTUAL 

 

* Quiero que la impresion en una imagen sea exactamente como cuando envio a la impresora.

 
* La Imagen del mismo tamaño/proporcional al del canvas de la impresora.
* El Texo impreso del mismo tamaño proporcional al la impresion del el canvas de la Impresora.
  (Aqui es donde existe basicamente el problema ya que segun el tamaño del FONT la imrpesion es mas corta en el preview). 
 
 
SI ALGUIEN Tiene una IDEA agredecere, algun tip que me ayude con este pequeño problema.
 
 
ANEXO MINICODIGO que utilizo para datos bases de las impresiones.
 
 

delphi
  1. Var
  2. preview : TImage.
  3.  
  4.  
  5. procedure InitPrinter;
  6. var
  7. XD,YD:Integer;
  8. x,y:string;
  9. begin
  10. if lPrinter then
  11. begin
  12. // pixels/inch horizontales
  13. XD:=GetDeviceCaps(Printer.Handle,LogPixelSX);
  14. // pixels/inch verticales
  15. YD:=GetDeviceCaps(Printer.Handle,LogPixelSY);
  16. nFx := XD/25.4;
  17. nFy := YD/25.4;
  18. nFx := nFx * 10;
  19. nFy := nFy * 10;
  20. nIncY:=0;
  21. printer.Canvas.brush.Style:=bsClear;
  22. end
  23. ELSE
  24. begin
  25. //Factores de Calculo Pixel/MM
  26. nFx := GetDeviceCaps(printer.Handle,LogPixelSX)/25.4;
  27. nFy := GetDeviceCaps(printer.Handle,LogPixelSY)/25.4;
  28.  
  29. //
  30. ////////////////////////////////////
  31. // CON ESTOS VALORES LA IMPRESION ES MUY SIMILAR A IMPRESORA
  32. ////////////////////////////////////
  33. //
  34.  
  35. nFx := 37.795275591;
  36. nFy := 37.795275591;
  37.  
  38.  
  39. x := floattostr(int(nFy*100));
  40. y := floattostr(int(nFX*100));
  41. nIncY:=0;
  42. preview.Height := strtoint(y);
  43. preview.Width := strtoint(x);
  44. preview.Canvas.brush.Style:=bsClear;
  45. preview.Picture := nil;
  46.  
  47.  
  48. end;
  49.  
  50. end;
  51.  
  52. procedure TipoLetra(cFont:String; nSize:Integer);
  53. begin
  54.  
  55. if lPrinter then
  56. begin
  57. printer.Canvas.font.Name := aLLTRIM(cFont);
  58. if nSize>0 then
  59. printer.canvas.Font.Size := nSize;
  60. end
  61. ELSE
  62. begin
  63. preview.Canvas.font.Name := AllTrim(cFont);
  64. if nSize>0 then
  65. preview.canvas.Font.Size := nSize;
  66. end;
  67.  
  68. end;
  69.  
  70. procedure Escribe(xPos:Extended;cValor,cMask:String);
  71. Var x,y:integer;
  72. begin
  73. xPos := int(xPos * nFx);
  74. x := strtoint(floattostr(xPos));
  75. if lPrinter then
  76. begin
  77. y:=printer.canvas.PenPos.y;
  78. cValor := Maskara(cValor,cMask);
  79. printer.Canvas.Brush.Style := bsClear;
  80. printer.Canvas.TextOut(x,y,cValor);
  81. end
  82. ELSE
  83. begin
  84. y:=preview.canvas.PenPos.y;
  85. cValor := Maskara(cValor,cMask);
  86. preview.Canvas.Brush.Style := bsClear;
  87. preview.Canvas.TextOut(x,y,cValor);
  88. end;
  89. end;
  90.  
  91.  
  92. procedure EscribeXY(x1,y1:Extended;cValor,cMask:String);
  93. Var
  94. x,y:integer;
  95. begin
  96.  
  97. x1 := int(x1 * nFx);
  98. y1 := int(y1 * nFy);
  99. x := strtoint(floattostr(x1));
  100. y := strtoint(floattostr(y1)) + nIncY;
  101. cValor := Maskara(cValor,cMask);
  102.  
  103. if lPrinter then
  104. begin
  105. printer.Canvas.Brush.Style := bsClear;
  106. printer.Canvas.TextOut(x,y,cValor);
  107. end
  108. else
  109. begin
  110. preview.Canvas.Brush.Style := bsClear;
  111. preview.Canvas.TextOut(x,y,cValor);
  112. end;
  113. Brinca(1);
  114. end;

 


Edited by pcicom, 13 April 2017 - 09:23 AM.

  • 0

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 13 April 2017 - 10:09 AM

En ocasiones he realizado algo similar a lo que haces, escribiendo en un HDC. Si el HDC es el dela impresora, imprime. Si el HDC es el de una ventana, previsualiza.
 
A vote pronto creo que tu problema está en los tipos en coma flotante. Usas una forma extrana pasando el resultado a un String y luego a float, imagino que es porque viste que perdías precisión, o algo así. Es mejor usar el tipo double para no perder precisión, pero lo que yo suelo hacer el usar la API MulDiv algo así:

delphi
  1. clientR.right = MulDiv(PageSize.cx, screenRes.cx, printRes.cx);

Así evito el uso de tipos de coma flotante cuando el final va a ser un entero.

Saludos.
  • 0

#3 pcicom

pcicom

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 267 posts
  • LocationMéxico

Posted 13 April 2017 - 10:40 AM

En ocasiones he realizado algo similar a lo que haces, escribiendo en un HDC. Si el HDC es el dela impresora, imprime. Si el HDC es el de una ventana, previsualiza.
 
A vote pronto creo que tu problema está en los tipos en coma flotante. Usas una forma extrana pasando el resultado a un String y luego a float, imagino que es porque viste que perdías precisión, o algo así. Es mejor usar el tipo double para no perder precisión, pero lo que yo suelo hacer el usar la API MulDiv algo así:


delphi
  1. clientR.right = MulDiv(PageSize.cx, screenRes.cx, printRes.cx);

Así evito el uso de tipos de coma flotante cuando el final va a ser un entero.

Saludos.

 

 

 

Gracias, por contestar mi estimado escafandra,  la verdad ya ni me acuerdo por que lo uso asi, ya que como comento es algo que desarrolle hace varios años, como comento en mi consulta..  mi bronca principal es cuando imprimo en una imagen a la que le llamo preview, y no se porque aplica principalmente a los FONTS que posiblemente no los escalo correctamente,  pero dentro de la logica siendo canvas el de la imagen y canvas el de la printer,  pues deberia de haber una correspondencia o algo parecido..

 

Es decir en el printer  existe el printer.pagewidth y printer.pageheight   y para utilizar una imagen cual deberia de ser sus correspondientes valores de width y height de tal manera que los FONTS correspondan en su tamaño natural..  osea que si en el printer.canvas.font.size = 10   en el image.canvas.font.size=10 sean iguales/correspondientes a tamaño..   esta es la base de mi problema...

 

Agredezco cualquier comentario, y mas siendo de los NOVATOS de DELPHI a los cuales me gusta leer tus aportes..     



 


  • 0

#4 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 13 April 2017 - 06:59 PM

Para escalar Windows nos propone las APIs SetMapMode, SetViewportExtEx y SetWindowExtEx. Para escalar un dispositivo, como la impresora, a la pantalla, la escala debe estar en proporción a las resoluciones de ambos. Las APIs SetViewportExtEx y SetWindowExtEx adaptan el canvas de un dispositivo al otro. Te pongo un ejemplo donde coloco en un formulario un TImage que servirá para previsualizar lo que se imprime en la impresora. El TImage debe tener un tamaño proporcional al papel usado, para ello se ajusta al crear el formulario. La impresión y la previsualización se hacen con la misma función que pinta directamente en el Canvas del dispositivo. La escala consigue adaptar el preview.


delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls, Printers, ExtCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Button1: TButton;
  12. Button2: TButton;
  13. Image1: TImage;
  14. procedure Button1Click(Sender: TObject);
  15. procedure Button2Click(Sender: TObject);
  16. procedure FormCreate(Sender: TObject);
  17. private
  18. { Private declarations }
  19. public
  20. { Public declarations }
  21. end;
  22.  
  23. var
  24. Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. {$R *.dfm}
  29.  
  30. procedure Draw(Canvas: TCanvas; var Rect: TRect);
  31. var
  32. TE: TSize;
  33. i: integer;
  34. begin
  35. Canvas.Font.Name:= 'arial';
  36. Canvas.Font.Size:= 195;
  37. Canvas.Brush.Style:= bsClear;
  38. Canvas.Rectangle(Rect);
  39. TE:= Canvas.TextExtent('HOLA');
  40. for i:= 0 to 3 do
  41. Canvas.TextOut((Rect.Right - TE.cx) div 2, i*TE.cy, 'HOLA');
  42. end;
  43.  
  44. procedure TForm1.Button1Click(Sender: TObject);
  45. var
  46. PrintRect: TRect;
  47. begin
  48. PrintRect:= Rect(0, 0, Printer.PageWidth-1, Printer.PageHeight-1);
  49. Printer.BeginDoc;
  50. Draw(Printer.Canvas, PrintRect);
  51. Printer.EndDoc;
  52. end;
  53.  
  54. procedure TForm1.Button2Click(Sender: TObject);
  55. var
  56. DocRect: TRect;
  57. screenRes, printRes: TSize;
  58. screenDC: HDC;
  59. begin
  60. screenDC:= Windows.GetDC(0);
  61. screenRes.cx:= GetDeviceCaps(screenDC, LOGPIXELSX);
  62. screenRes.cy:= GetDeviceCaps(screenDC, LOGPIXELSY);
  63. Windows.ReleaseDC(0, screenDC);
  64.  
  65. printRes.cx:= GetDeviceCaps(Printer.Handle, LOGPIXELSX);
  66. printRes.cy:= GetDeviceCaps(Printer.Handle, LOGPIXELSY);
  67.  
  68. DocRect.left:= 0;
  69. DocRect.top:= 0;
  70. DocRect.right:= MulDiv(Printer.PageWidth, screenRes.cx, printRes.cx);
  71. DocRect.bottom:= MulDiv(Printer.PageHeight, screenRes.cy, printRes.cy);
  72.  
  73. SetMapMode(Image1.Canvas.Handle, MM_ISOTROPIC);
  74.  
  75. SetViewportExtEx(Image1.Canvas.Handle, Image1.Width, Image1.Height, nil);
  76. // Escala la ventana al tamaño logico de la pagina (asume left = top = 0)
  77. SetWindowExtEx(Image1.Canvas.Handle, DocRect.right, DocRect.bottom, nil);
  78.  
  79. Draw(Image1.Canvas, DocRect);
  80. end;
  81.  
  82. procedure TForm1.FormCreate(Sender: TObject);
  83. begin
  84. Image1.Height:= MulDiv(Printer.PageHeight, Image1.Width, Printer.PageWidth);
  85. end;
  86.  
  87. end.

c088156ebf7463d88e489ef378e39c3do.gif

 

 

Subo el proyecto probado con Delphi7  en Windows10.

 

 

 

Saludos.

Attached Files


  • 1

#5 foxito

foxito

    Newbie

  • Miembros
  • Pip
  • 1 posts

Posted 02 July 2022 - 11:19 AM

me puedes proporcionar tu correo


  • 0

#6 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14460 posts
  • LocationMéxico

Posted 04 July 2022 - 08:46 AM

me puedes proporcionar tu correo

 

Hola foxito, bienvenido a DelphiAccess

 

¿Tienes alguna pregunta? Este medio es el óptimo para ello ya que ayudará a mas compañeros.

 

Saludos


  • 0




IP.Board spam blocked by CleanTalk.