Hola invitado         31 Jul, 2010 - 07:53
Menú principal
 
Ads
 
Patrocinadores
 
Anuncios
 
© 2009 PortalFox
Dar justificación completa a textos en informe con GdiPlus X (Cesar Chalom) Trad lecturas 2343
 Enviado por amby en Viernes, 11 Abril, 2008
Artículos En esta segunda entrega, Cesar extiende la solución mostrada antes para justificar textos, brindando ahora la posibilidad de hacerlo en informes de VFP.

Dar justificación completa a textos en informe con GdiPlus X

Artículo original: Full Justified Texts in your reports with GdiPlus X
http://weblogs.foxite.com/cesarchalom/archive/2007/04/05/3641.aspx
Autor: Cesar Chalom (http://weblogs.foxite.com/cesarchalom)
Traducido por: Ana María Bisbé York (amby@telefonica.net)
Para: PortalFox (http://www.portalfox.com)


Esta es la continuación a mi entrada anterior, "Full-Justified Text with GdiPlusX". Ahora mostraré cómo podemos utilizar el nuevo método DRAWSTRINGJUSTIFIED de la biblioteca GdiPlusX para justificar completamente textos en nuestros informes.

Existen dos vías para utilizar esta característica en informes.

Lo más obvio es utilizar la imagen guardada en ejemplos del escrito anterior, y utilizarla directamente en el informe.

Pero VFP9 ofrece además muchas otras posibilidades que no podemos dejar sin probar, por lo que decidí crear una subclase del Report Listener que transformaría algunos de los textos de mis informes en Totalmente justificados. Mi idea era que el usuario podría necesitar agregar una etiqueta  "<FJ>" en el inicio de cualquier cadena de un cuadro de texto en un informe, para decirle a mi ReportListener que dibujara el texto utilizando el método DRAWSTRINGJUSTIFIED  de GdiPlusX.

Tenga en cuenta por favor, que NO soy un experto en Informes asistidos por objetos en VFP 9. Mi experiencia utilizando los Report Listeners es muy limitada. Estoy seguro de que el report listener que se muestra debajo puede ser mejorado, así que si tiene cualquier sugerencia que pueda mejorar la calidad del proceso o hacerlo más sencillo, ¡ dígamelo por favor !

¡ A los gurús de informes ! Colin, Lisa, Doug, Cathy, Dorin, Garret, Craig, Bo y otros... estaría muy agradecido si pudieran echar un vistazo al código que está debajo, y mandar sus comentarios ... ¡ y sugerencias !

En cualquier caso, esto funciona bien.

Mi "FullJustifyListener" realiza las siguientes acciones:

  •  Inicializa GdiPlusX
  •  Crea un objeto Graphics GDI+ que será utilizado para dibujar en el informe
  •  Guarda en una matriz la información requerida para dibujar la cadena (Font, Size, Style y Color)
  •  Antes de generar la cadena, verifica si la etiqueta "<FJ>" está al inicio del texto, si está, dibuja la cadena utilizando el nuevo método.

MUY IMPORTANTE - ¡ LEA ESTO !

Todos los ejemplos requieren tener la última versión, 0.08A que está en planes de ser liberada. Está un poco oculto en Codeplex, por lo que apunto el enlace directo para la descarga:

http://www.codeplex.com/VFPX/Release/ProjectReleases.aspx?ReleaseId=1711

La parte principal de GDI+ del report listener está ubicada en la subclase "Render".

Por favor, copie y pegue el código que está a continuación y guárdelo como FJLISTENER.PRG en la carpeta Samples de GdiPlusX

DEFINE CLASS FullJustifyListener AS _ReportListener OF ;
    ADDBS(HOME(1)) + "FFC\_ReportListener.VCX"
    oGDIGraphics = NULL
  DIMENSION aRecords[1]
  * Antes de ejecutar el informe, necesitamos estar seguros de que fue inicializado GdiPlusX
  * y crear un nuevo objeto Graphics
  FUNCTION BEFOREREPORT
    DODEFAULT()
    WITH This
      * Verificar si ya tenemos el objeto "System" en "_Screen"
      IF NOT PEMSTATUS(_Screen,"System",5)
        _SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE("system.vcx")))
      ENDIF
      .oGDIGraphics = _SCREEN.SYSTEM.Drawing.Graphics.New()
      .SetFRXDataSession()
      DIMENSION .aRecords[reccount(), 12]
      .ResetDataSession()
    ENDWITH
  ENDFUNC

  FUNCTION BEFOREBAND(nBandObjCode, nFRXRecNo)
    This.SharedGDIPlusGraphics = This.GDIPLUSGRAPHICS
    This.oGDIGraphics.Handle = This.SharedGDIPlusGraphics
    DODEFAULT(nBandObjCode, nFRXRecNo)
  ENDFUNC

  PROCEDURE RENDER(tnFRXRecNo,;
      tnLeft,tnTop,tnWidth,tnHeight,;
      nObjectContinuationTyENDFUNC

  PROCEDURE RENDER(tnFRXRecNo,;
      tnLeft,tnTop,tnWidth,tnHeight,;
      nObjectContinuationType, ;
      cContentsToBeRendered, GDIPlusImage)
    LOCAL lcText
    lcText = This.aRecords(tnFRXRecNo,1)
    IF VARTYPE(lcText) = "C" AND lcText = "<FJ>"
        lcText = SUBSTR(lcText,5) && Quitar la etiqueta <FJ> de la cadena
      This.oGDIGraphics.Handle = This.GDIPlusGraphics
      WITH _SCREEN.SYSTEM.Drawing
        * Crear un objeto GDI+ Rectangle que especifique
        * el área donde vamos a dibujar el texto.
        LOCAL loRectF as xfcRectangleF
        loRectF = .RectangleF.New(tnLeft, tnTop, tnWidth, tnHeight)
        * Crear un objeto Font basado en la configuración original del informe
        LOCAL loFont as xfcFont
        loFont = .Font.New(This.aRecords(tnFRXRecNo,2) ;
          , This.aRecords(tnFRXRecNo,4), This.aRecords(tnFRXRecNo,3) ;
          , .GraphicsUnit.Point)
        * Si tenemos un fondo opaco para el texto,
        * entonces dibujar un rectángulo utilizando el fondo escogido
        IF This.aRecords[tnFRXRecno,8] <> 0 && Alpha
          * Obtener los colores de fondo
          LOCAL lnRed, lnGreen, lnBlue, lnAlpha
          lnRed = This.aRecords[tnFRXRecno,5]
          lnGreen = This.aRecords[tnFRXRecno,6]
          lnBlue = This.aLOCAL loBackBrush as xfcSolidBrush
          loBackBrush = .SolidBrush.New(;
            .Color.FromArgb(lnAlpha,lnRed, lnGreen, lnBlue))
          * Dibujar el rectángulo de fondo
          This.oGDIGraphics.FillRectangle(loBackBrush, tnLeft, tnTop, tnWidth, tnHeight)
        ENDIF
        * Obtener los colores para el texto
        lnRed = This.aRecords[tnFRXRecno,9]
        lnGreen = This.aRecords[tnFRXRecno,10]
        lnBlue = This.aRecords[tnFRXRecno,11]
        lnAlpha = This.aRecords[tnFRXRecno,12]
        * Crear una brocha sólida que se utilizará para dibujar el texto
        LOCAL loTextBrush as xfcSolidBrush
        loTextBrush = .SolidBrush.New(;
          .Color.FromArgb(lnAlpha,lnRed, lnGreen, lnBlue))
        * Finalmente, dibujar el texto en modo FullJustified.
        This.oGDIGraphics.DrawStringJustified(lcText, loFont, loTextBrush, loRectF)
      ENDWITH
    ELSE
      * Si no dibujamos una cadena completamente justificada,
      * dejamos que VFP dibuje el texto como siempre.
      DODEFAULT(tnFRXRecNo, tnLeft, tnTop, tnWidth, tnHeight, ;
        nObjectContinuationType, cContentsToBeRendered, GDIPlusImage)
    ENDIF
    * Como dibujamos el texto, no deseamos
    * que ocurra el comportamiento predeterminado.
    NODEFAULT
  ENDPROC

  FUNCTION EvaluateContents(tnFRXRecNo, toObjProperties)
    * Obtener los datos del FRX
    This.aRecords[tnFRXRecno,1] = toObjProperties.Text
    This.aRecords[tnFRXRecno,2] = toObjProperties.FontName
    This.aRecords[tnFRXRecno,3] = toObjProperties.FontStyle
    This.aRecords[tnFRXRecno,4] = toObjProperties.FontSize
    This.aRecords[tnFRXRecno,5] = toObjProperties.FillRed
    This.aRecords[tnFRXRecno,6] = toObjProperties.FillGreen
    This.aRecords[tnFRXRecno,7] = toObjProperties.FillBlue
    This.aRecords[tnFRXRecno,8] = toObjProperties.FillAlpha
    This.aRecords[tnFRXRecno,9] = toObjProperties.PenRed
    This.aRecords[tnFRXRecno,10] = toObjProperties.PenGreen
    This.aRecords[tnFRXRecno,11] = toObjProperties.PenBlue
    This.aRecords[tnFRXRecno,12] = toObjProperties.PenAlpha
  ENDFUNC
ENDDEFINE

Esto es muy fácil de utilizar

Abra un informe, y seleccione un cuadro de texto que tenga asociado un campo memo. En el campo propiedades, seleccione la ficha General, en "Expression" añada la cadena "<fj>" antes del campo original. Suponiendo que usted tiene la expresión "MiTabla.MiCampoMemo", para poderlo justificar, cámbielo por: "<fj>"+MiTabla.MiCampoMemo.</fj></fj>

El siguiente paso es asegurarse de que VFP utilizará nuestro listener para generar el informe.

* Decir a VFP que utilizaremos las nuevas características de informes
SET REPORTBEHAVIOR 90
LOCAL loReportListener
loReportListener = NEWOBJECT("FullJustifyListener",LOCFILE("FJListener.prg"))
* loReportListener = CREATEOBJECT("FullJustifyListener")
loReportListener.LISTENERTYPE = 1
REPORT FORM MyReport OBJECT loReportListener


ACTUALIZADO 07/04/2007

Después de algunas sugerencias de Victor Espinoza, debajo está la versión modificada de la clase "FJListener", que va a obtener la etiqueta <FJ> del campo user data del cuadro de texto (que está debajo de la ficha "Otros"), de esta forma la etiqueta "<FJ>" no afectará al informe si más tarde se decide utilizar un report listener alternativo.

* Programa : FJLISTENER.PRG
* * Objetivo : Obtener un Report Listener que permita generar textos
* con alineación totalmente justificada.
* Autores : Cesar Chalom y Victor Espinoza
* La clase está basada en el artículo "Listening to a report" por Doug Hennig
* http://msdn2.microsoft.com/en-us/library/ms947682.aspx

DEFINE CLASS FullJustifyListener AS _ReportListener OF ;
    ADDBS(HOME(1)) + "FFC\_ReportListener.VCX"
    oGDIGraphics = NULL
  DIMENSION aRecords[1]

  * Doug Hennig - Si no está configurado aun la propiedad ListenerType,
  * configurar basado en si el informe será previsualizado o impreso.
  FUNCTION LoadReport
    WITH This
      DO CASE
        CASE .ListenerType <> -1
        CASE .CommandClauses.Preview
          .ListenerType = 1
        CASE .CommandClauses.OutputTo = 1
          .ListenerType = 0
      ENDCASE
    ENDWITH
    DODEFAULT()
  ENDFUNC

  * Antes de ejecutar el informe, necesitamos estar seguros de que fue inicializado GdiPlusX
  * y crear un nuevo objeto Graphics
  FUNCTION BEFOREREPORT
    DODEFAULT()
    WITH This
      * Verificar si ya tenemos el objeto "System" en "_Screen"
      IF NOT PEMSTATUS(_Screen,"System",5)
      _SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE("system.vcx")))
    ENDIF

    .oGDIGraphics = _SCREEN.SYSTEM.Drawing.Graphics.New()
    .SetFRXDataSession() && activa la sesión de datos del cursor FRX
    DIMENSION .aRecords(RECCOUNT(), 13)
    SCAN FOR "<FJ>" $ UPPER(User)
      .aRecords(RECNO(), 13) = "FJ"
        ENDSCAN
      .ResetDataSession() && restablece datasession ID a la sesión de datos donde está el listener
    ENDWITH
  ENDFUNC

  FUNCTION BEFOREBAND(nBandObjCode, nFRXRecNo)
    This.SharedGDIPlusGraphics = This.GDIPLUSGRAPHICS
    This.oGDIGraphics.Handle = This.SharedGDIPlusGraphics
    DODEFAULT(nBandObjCode, nFRXRecNo)
  ENDFUNC

  PROCEDURE RENDER(tnFRXRecNo,;
      tnLeft,tnTop,tnWidth,tnHeight,;
      nObjectContinuationType, ;
      cContentsToBeRendered, GDIPlusImage)
    IF VARTYPE(This.aRecords(tnFRXRecNo,13)) = "C" AND ;
        This.aRecords(tnFRXRecNo,13) == "FJ"
        LOCAL lcText
      lcText = This.aRecords(tnFRXRecNo,1)
      This.oGDIGraphics.Handle = This.GDIPlusGraphics
      WITH _SCREEN.SYSTEM.Drawing
        * Crear un objeto GDI+ Rectangle que especifique
        * el área donde vamos a dibujar el texto.
        LOCAL loRectF as xfcRectangleF
        loRectF = .RectangleF.New(tnLeft, tnTop, tnWidth, tnHeight)
        * Crear un objeto Font basado en la configuración original del informe
        LOCAL loFont as xfcFont
        loFont = .Font.New(This.aRecords(tnFRXRecNo,2) ;
          , This.aRecords(tnFRXRecNo,4), This.aRecords(tnFRXRecNo,3) ;
          , .GraphicsUnit.Point)
        * Si tenemos un fondo opaco para el texto,
        * entonces dibujar un rectángulo utilizando el fondo escogido
        IF This.aRecords[tnFRXRecno,8] <> 0 && Alpha
          * Obtener los colores de fondo
          LOCAL lnRed, lnGreen, lnBlue, lnAlpha
          lnRed = This.aRecords[tnFRXRecno,5]
          lnGreen = This.aRecords[tnFRXRecno,6]
          lnBlue = This.aRecords[tnFRXRecno,7]
          lnAlpha = This.aRecords[tnFRXRecno,8]
          * Crear una brocha sólida que se utilizará para dibujar el fondo
          LOCAL loBackBrush as xfcSolidBrush
          loBackBrush = .SolidBrush.New(;
            .Color.FromArgb(lnAlpha,lnRed, lnGreen, lnBlue))
          * Dibujar el rectángulo de fondo
          This.oGDIGraphics.FillRectangle(loBackBrush, tnLeft, tnTop, tnWidth, tnHeight)
        ENDIF
        * Obtener los colores del texto
        lnRed = This.aRecords[tnFRXRecno,9]
        lnGreen = This.aRecords[tnFRXRecno,10]
        lnBlue = This.aRecords[tnFRXRecno,11]
        lnAlpha = This.aRecords[tnFRXRecno,12]
        * Crear una brocha sólida que utilizaremos para dibujar el texto
        LOCAL loTextBrush as xfcSolidBrush
        loTextBrush = .SolidBrush.New(;
          .Color.FromArgb(lnAlpha,lnRed, lnGreen, lnBlue))
        * Finalmente, dibujar el texto en modo FullJustified.
        This.oGDIGraphics.DrawStringJustified(lcText, loFont, loTextBrush, loRectF)
      ENDWITH
    ELSE
      * Si no dibujamos una cadena completamente justificada,
      * dejamos que VFP dibuje el texto como siempre..
      DODEFAULT(tnFRXRecNo, tnLeft, tnTop, tnWidth, tnHeight, ;
        nObjectContinuationType, cContentsToBeRendered, GDIPlusImage)
    ENDIF
    * Como dibujamos el texto, no deseamos
    * que ocurra el comportamiento predeterminado.
    NODEFAULT
  ENDPROC

  FUNCTION EvaluateContents(tnFRXRecNo, toObjProperties)
    * Obtener los datos del FRX
    This.aRecords[tnFRXRecno,1] = toObjProperties.Text
    This.aRecords[tnFRXRecno,2] = toObjProperties.FontName
    This.aRecords[tnFRXRecno,3] = toObjProperties.FontStyle
    This.aRecords[tnFRXRecno,4] = toObjProperties.FontSize
    This.aRecords[tnFRXRecno,5] = toObjProperties.FillRed
    This.aRecords[tnFRXRecno,6] = toObjProperties.FillGreen
    This.aRecords[tnFRXRecno,7] = toObjProperties.FillBlue
    This.aRecords[tnFRXRecno,8] = toObjProperties.FillAlpha
    This.aRecords[tnFRXRecno,9] = toObjProperties.PenRed
    This.aRecords[tnFRXRecno,10] = toObjProperties.PenGreen
    This.aRecords[tnFRXRecno,11] = toObjProperties.PenBlue
    This.aRecords[tnFRXRecno,12] = toObjProperties.PenAlpha
  ENDFUNC
ENDDEFINE

Por ahora esto me parece bien. Pero existen muchas cosas que se deben mejorar. Para la siguiente versión pudiera ser una directiva que se utilice junto con los otros report listeners, como hizo Doug Hennig en su gran artículo "Listening to a Report".

Enlaces relacionados que me ayudaron a entender cómo trabaja el Report Listener:

Nota de la traductora: Estos artículos están traducidos y publicados en PortalFox


 Versión imprimible  
Dar justificación completa a textos en informe con GdiPlus X (Cesar Chalom) Trad | Entrar/Crear una cuenta | 0 Comentarios
Los comentarios son propiedad de sus respectivos autores.
No somos responsables de su contenido.



Todas las marcas y los logos utilizados en este sitio son propiedad de sus respectivos dueños.
Los artículos, noticias y comentarios son propiedad y responsabilidad de sus respectivos autores.
Copyright © 2000-2010 PortalFox. Todos los derechos reservados.