PDA

Ver la Versión Completa : Raro resultado al convertir mm a pixels para usar con QuickRepor


rolandoj
29-06-2013, 20:45:11
Hola a todos,

Tengo una duda acerca de la equivalencia de MM a Pixels con QuickReport.

Para ponerlo en contexto, empiezo diciendo que mi problema básico era poner sobre un panel TLabels que luego deberían convertirse a TQRLabel y ponerlos sobre una banda de quickreport.

Para ello necesito que el panel tenga en pixels el mismo ancho que la banda de QuickReport.

La idea es simple a partir de que mis QuickReports manejan tamaños de hojas de papel en mm, y los bordes también. así que el ancho de banda en mm es el ancho del papel menos el margen izquierdo y menos el margen derecho.

Por tanto, el ancho del panel debería ser simplemente pasar ese ancho en mm a pixels.

Para esto último uso lo siguiente


Var
AnXScale: Double:
HRes,HSiz: Integer;

Begin
// otras líneas

HRes := GetDeviceCaps(AHandle,HORZRES);
HSiz := GetDeviceCaps(AHandle,HORZSIZE);
// Factor de escala
AnXScale := HRes;
AnXScale := AnXScale / HSiz;

Sin embargo, cuando se ejecuta el programa, el factor de Escala AnXScale, para mi monitor y configuración de pantalla, da 3.63 mientras que el que QuickReport está aplicando es de 3.77, una diferencia demasiado grande para justificarla con errores de redondeo.

Akguien sabe que puede estar pasando ?. Me falta algo en el cálculo ?

Agradezco cualquier comentario

Casimiro Notevi
29-06-2013, 22:57:14
Que yo sepa, un pixel llevado a "la vida real" no tiene un tamaño fijo, y es distinto entre diferentes monitores.

rolandoj
30-06-2013, 03:18:27
Hola Casimiro,

Muchas gracias por comentar.

Si, claro, el pixel varía entre monitores; por eso es el cálculo que hago de determinar a que equivale el pixel en mi monitor en particular.

Para ser consistente, comparo contra el cálculo que hace QuickReport en mi mismo monitor; ya que, por lo expuesto, si usaramos otro monitor se sería lógico que nos diera diferente.

El caso es que están dando diferente con el "mismo monitor". Yo pensaría que QuickReport, al hacer la conversión, debería seguir básicamente mi mismo proceso; pero, no lo hace. La pregunta es : Por qué ?

Casimiro Notevi
30-06-2013, 10:10:01
Yo pensaría que QuickReport, al hacer la conversión, debería seguir básicamente mi mismo proceso; pero, no lo hace. La pregunta es : Por qué ?
Ese es el problema, "tú pensarías que quickreport hace el mismo proceso", pero lo que tú pienses puede ser distinto de lo que hace quickreport :D
Deberías saber cómo lo hace quickreport, ¿no tienes acceso al código fuente o en algún lugar de la documentación?
Es que estarás "dando palos de ciego" mientras no te asegures de ese tema.

rolandoj
30-06-2013, 19:38:02
Hola Casimiro,

Si, ese es el problema. Por eso pregunto aquí.

Es que la lógica indica que para tener una vista preliminar en pantalla, como lo hace QuickReport, las posiciones y tamaños de los campos en mm deben ser las que efectivamente se van a imprimir; pero, en pantalla se despliega en Pixels (y las medidas de los componentes QuickReport están en pixels), luego deben convertirse los mm a pixels.

Como hacerlo es el problema. El método que empleo es lo lógico; pero, como dije antes, la evidencia indica que no es el mismo que usa Quick Report. La gran pregunta es por qué ? (bueno, y por supuesto, que método usa '). En este momento ni siquiera se me ocurre una razón para usar un método distinto.

Lepe
01-07-2013, 17:04:01
Todos los generadores de informes que conozco, trabajan en twips ( 1 pulgada tiene 1440 twips si no recuerdo mal), ya que es una medida independiente del dispositivo (papel, impresora, pantalla, escaner). Para colmo de males, se tiene en cuenta la propiedad del Form PixelPerInch (varía al usar fuentes grandes o normales en windows).

Cuando trabajé con Reportman (la versión OpenSource), usé estas conversiones:

1440 twips 2.54 cms
twips_per_Inch = ------------ cms_per_Inch = ---------
1 Inch 1 Inch

72 pixels
pixels_per_inch = -----------
1 inch
-----------------------------------------------------------------------------}


Estas rutinas están hechas por mí (editado, porque me equivoqué antes):

const
CMS_PER_INCHESS=2.54;
TWIPS_PER_INCHESS=1440;
POINTS_PER_INCHESS=72;


function PixelsToTwips(apixels:integer):integer;
begin
Result:=Round((APixels/(Screen.PixelsPerInch))* TWIPS_PER_INCHESS);
end;

function TwipsToPixels(atwips:integer):integer;
begin
Result:=Round((atwips *Screen.PixelsPerInch) / TWIPS_PER_INCHESS);
end;


Estas otras, son de ReportMan (Open Source):

type
TRpTwips=integer;
function twipstoinchess(twips1:TRpTwips):double;
begin
Result:=twips1/TWIPS_PER_INCHESS;
end;

function twipstocms(twips1:TRpTwips):double;
begin
Result:=(twips1/TWIPS_PER_INCHESS)*CMS_PER_INCHESS;
end;

Te recomiendo (por el bien de tu salud mental ;)) uses siempre una sola unidad, todo en twips, y, si tienes que mostrar algo al usuario, entonces haces al conversión a pixels o pulgosos.

Saludos

rolandoj
01-07-2013, 18:44:38
Hola Lepe,

Muchas gracias por el dato.

Toca analizar esto con calma; empezando porque yo nunca he trabajado en pulgadas.

Por otra parte, no entiendo la necesidad de pasar la escala a trabajar con pulgadas; en últimas las pulgadas son covertibles a mm y lo máximo que debería haber de diferencia son errores de redondeo.

Entiendo que los generadores trabajen internamente así porque pulgadas sea la unidad de medida de sus países; pero, por eso no debería haber diferencias

Lo que más me causa curiosidad es que ese método que muestras parece operar ignorando que, en general, la resolución horizontal de pantalla es distinta a la resolución vertical; como es indicado por la función GetDeviceCaps que yo estoy usando.

Puede que tengas razón en lo de cuidar la salud mental; pero, no me gusta hacer cosas sin entender la razón de las mismas. Para mi el aspecto conceptual es importante más allá de que operativamente las cosas funcionen.

anubis
02-07-2013, 05:09:45
Bueno si me lo permitis, he visto el mismo problema con los informes de fortesreport en lazarus.
Como sabeis para crear un report lo tienes que añadir a un form (por lo menos lo hago asi) y luego le voy poniendo los campos.

Bueno, segun la hoja que le puse 1 cm de margen, coloco el label a un cm y ahi me marca 40 pixels.

Por el otro lado, tenia algun report ya creado e impreso, y compare las medidas, mas o menos se ajustan a 40 pixeles, en algunos casos, 3.6, nose si se ajusta a la realidad.

De todas formas probare el metodo que comentais ;).

rolandoj
02-07-2013, 05:23:41
Hola Anubis,

Muchas gracias por el aporte.

Con eso, el asunto me intriga más.

Ojalá algún colega pueda traer una explicación. Tiene que existir alguna razón en el fondo de este asunto; pero, no deja de ser muy raro.

Milímetros y pulgadas son medidas exactas independientemente de si estamos en un monito o sobre un papel. El pixel si cambia segùn el monitor y la resolución que tenga; pero, como las anteriores son exactas, el mètodo para convertir de una resolución específica de un monitor específico a ellas debería ser el mismo; y hasta donde sé debería usar el GetDeviceCaps de Windows que se supone que se implementó para soportar ese tema.

Saludos

Lepe
03-07-2013, 00:21:43
rolandoj, se ve que no has entendido mi mensaje anterior. La unidad por excelencia en generadores de informes es el twip (http://es.wikipedia.org/wiki/Twip), ni pulgadas, ni milímetros, repito es el twip.

Si no entiendes por qué, entonces crea tu propio generador de informes, desde cero, y seguro en algún punto, entenderás por qué nació el twip.

No te enfoques en "como tú crees que debe ser", enfócalo de la misma forma que FreeReports, FastReport, QuickReport, Reportman, Crystal Reports y todo parece que fortesreport también. Se necesita una unidad de medida que sea lógica, que no dependa de ninguna unidad física ni dispositivo, por eso se creó el twips (ni dependa de mm, ni inch, ni nada). Ten en cuenta que casi todos tratan un informe como una imagen (al fin y al cabo tienen que pintar en distintos dispositivos físicos). No te centres en el papel que sale... céntrate en el formato interno que la impresora tiene que diseñar para luego decirle al cabezal donde y como debe imprimir.

Piensa en los scaners, que tienen distinta profundida de escaneo (dpi 300 pixels por pulgada, 600, etc). Si una pulgada se escanea con 300 puntos de calidad, no es lo mismo que a 600. Por eso se creó la unidad twip. Porque así lo pasas todo a twips y trabajas sin importar la calidad del dispositivo que muestra el informe (monitor de 17 ó de 22 pulgadas, ancho o extra-ancho, con relación de aspecto 16:9, 4:3 ó 16:10... eso da igual, lo ponemos todo en twips y listo.

rolandoj
03-07-2013, 04:48:35
Hola Lepe,

Gracias por ampliar tú explicación. Me diste una idea:

La posibilidad de que las propiedades de los componentes QuickReport estén en twips y no en pixels como yo pensaba. Esa hubiese sido una explicación perfecta para las diferencias; sin embargo, verifiqué y no es cierto. Las propiedades Height y Width de la banda están en Pixels.

Ahora, creo que yo también debo ampliar la explicación de mi objetivo.

La impresión final la manejará QuickReport, e internamente manejará twips; pero, a mi lo que me interesa es tener posiciones y dimensiones de los campos sobre el panel para crear, a tiempo de ejecución, los TLabels, a partir de los cuales se generarán los respectivos TQRLabels que irán sobre la franja

Las posiciones y dimensiones tanto de la franja como los TQRLabels las expone QuickReport en Pixels. En el caso de los TQRLabel puedo entonces asignar directamente las propiedades de sus TLabels análogos; pero, en el caso de la banda es diferente porque las propiedades que demarcan los márgenes las expone en MM (bueno, pueden usarse otras unidades; pero, ninguna es TWIP).

Por tanto, el verdadero problema es calcular el ancho del panel en pixels teniendo como entradas el ancho de la hoja en pixels y el ancho de los márgenes en MM. Por eso es que lo que realmente interesa es pasar de MM a Pixels.

Ahora, lo que tú propones es pasar primero de MM a twips para luego pasar de twips a Pixels. Debería ser lo mismo que pasar de MM a Pixels directamente; pero, hay un detalle :

Las fórmulas que indicas son en función PixelsPerInch. Ignoran el hecho de que el tamaño horizontal del pixel podría ser diferente del tamaño vertical; lo que estaría diciendo que con esas fórmulas las dimensiones físicas en pantalla podrían no coincidir con las de papel y eso es lo que no entiendo porque se supone que las dimensiones físicas deben ser idénticas.

Si se estuviera aplicando un Zoom sería entendible; pero, estamos en un escenario de tamaño natural.

Bueno, de todas formas voy a probar y les cuento si coincidieron

rolandoj
03-07-2013, 18:34:24
Por tanto, el verdadero problema es calcular el ancho del panel en pixels teniendo como entradas el ancho de la hoja en pixels y el ancho de los márgenes en MM.

Perdón, aquí me equivoqué. El ancho de la hoja también está en MM, no en pixels como escribí.

Es claro : Ancho de la banda = ancho de la hoja - ancho del margen izquierdo - ancho del margen derecho.

Por mi configuración, las 3 variables usadas para el cálculo las da QuickReport en MM. Luego el ancho de la banda está en milímetros y ese valor debe quedar en Pixels para poder asignar al panel

Con eso en mente, probé con las fórmulas de Lepe; pero, tampoco me cuadra. De odas formas, voy a seguir revisando a v er si es que en algún momento posterior actualiza los valores y yo no me estoy dando cuenta.

anubis
04-07-2013, 07:21:35
A mi me interesa lo mismo, poder, en tiempo de ejecucion, cambiar las posiciones de lo que quiero imprimir en funcion de determinadas plantillas. Los datos se los pondria en mm y ya con el cambio a twips se colocarian en la posicion correcta.

Por mi parte todavia no lo pruebo, porque todavia estoy viendo si los datos de las plantillas las guardo en una base de datos o en un archivo ini (teniendo en cuenta que son varios tipos de hojas).

No creo que haya que darle muchas vueltas

Lepe
04-07-2013, 12:59:42
No buscareis un listado por columnas ¿no?

Porque si es así, la rutina QrCreateList crea el listado automático.

anubis
11-07-2013, 07:25:48
Hola,

No, a mi lo que me interesa es hacer una configuracion en la que yo le ponga las distancias en milimetros de los campos que quiero imprimir, y cuando imprima salga a las distancias que he marcado y tener un perfil para cada tipo de pagina, lo que nose es si estas cosas se guardan en una tabla de la base de datos o directamente en un ini.

Claro que dependera de cuantos perfiles tenga planeados, me convendra en un formato u otro. ;).

Lepe
11-07-2013, 12:04:05
Para eso la versión de pago de QR, que tiene un editor de plantillas. Te quitaría mucho trabajo y lo diseñas en un IDE. Después guardas la plantilla y listo. Por supuesto puedes modificarlo después con código, para añadir extras. Pero al menos la cabecera y pie de página, lo configuras con el editor.

Lo ideal es en la BBDD si es multiusuario, para tenerlo en un solo sitio. Además, si el usuario cambia de puesto, no necesita llevarse el .ini, no se puede borrar accidentalmente, etc.