Welcome to Foxite.COM Community Weblog Sign in | Join | Help



A sample on how to add features to Report Listener

VFP 9 introduces a new reporting system based on listeners (object-assisted output).

Listeners can be customized in a variety of ways and there's a lot of amazing things you can do with it.

If you combine the power of GDI+ with customized listeners you can highly increase the reporting capabilities.

I'll show how you can customize the Report Listener to create a watermark in all report pages and how you can customize Report Preview to change the language of report preview toolbar buttons and display the preview window maximized.

Set Classlib To (Addbs(Home()) + "FFC\_GDIPlus.vcx") Additive

* Create a Report Listener object
Local loReportListener
loReportListener = Newobject("MyReportListener")
With loReportListener
   .ListenerType = 1 && Preview
   * Set the Watermark properties: text, font and style
   .cWatermark = "Watermark demo"
   .cFontName = "Verdana"
   .nFontStyle = 1 && Bold
Endwith

* Create a cursor that will be the report data source and insert some records
Create Cursor curTest (field1 c(100))
Local i
For i=1 To 640
   Insert Into curTest Values (Str(i)+" test, test, test, test, test, test, test, test, test, test, test, test, test")
Endfor
Select curTest
Go Top

* Create a report on the fly
Create Report Test From curTest

* Run the report using the new report engine (object-assisted output)
Report Form Test Object loReportListener

* Close cursor and delete the report file
Use In curTest
Delete File Test.fr?
Return

* Create a class derived from _ReportListener base class and add some features
Define Class MyReportListener As _ReportListener Of Addbs(Home()) + "FFC\_ReportListener.VCX"
   * Internal to the class
   Hidden nAngle, oBrush, oColor, oFont, oGDIGraphics, oRect, oStringFormat
   Hidden ResourceStatus
   nAngle = 0
   oBrush = Null
   oColor = Null
   oFont = Null
   oGDIGraphics = Null
   oRect = Null
   oStringFormat = Null
   cResourceStatus = Set("Resource")
   * Public
   cWatermark = ""
   cFontName = ""
   nFontStyle = 0
   *
   Procedure Init
      Lparameters cWatermark, cFontName, cFontStyle
      Set Resource Off
      With This
         .cWatermark = Evl(cWatermark,"")
         .cFontName = Evl(cFontName,"")
         .nFontStyle = Evl(cFontStyle,0)
      Endwith
      DoDefault()
   Endproc
   *
   Procedure Destroy
      Local lcResourceStatus
      lcResourceStatus = This.cResourceStatus
      Set Resource &lcResourceStatus
      DoDefault()
   Endproc
   *
   Procedure LoadReport
      DoDefault()
      With This
         If .ListenerType==1 And Not Vartype(.PreviewContainer)=="O"
            .ExtendPreviewContainer()
         Endif
      Endwith
   Endproc
   *
   Procedure BeforeReport
      DoDefault()
      With This
         If Not Empty(.cWatermark)
            .oGDIGraphics = Createobject('GPGraphics')
            .SetWatermarkFontSize()
         Endif
      Endwith
   Endproc
   *
   Procedure AfterBand(nBandObjCode, nFRXRecNo)
      If nBandObjCode==7 && Page footer
         With This
            If Not Empty(.cWatermark)
               .AddWatermark()
            Endif
         Endwith
      Endif
      DoDefault(nBandObjCode, nFRXRecNo)
   Endproc
   *
   Function SetWatermarkFontSize
      With This
         .SetoGDIGraphicsHandle()

         * Create a semi transparent Grey Color
         .oColor = Createobject('gpColor',128,128,128,127)

         * Create a SolidBrush with Grey Color
         .oBrush = Createobject("gpSolidBrush", .oColor)

         * Create a StringFormat
         #Define StringAlignmentNear 0
         #Define StringAlignmentCenter 1
         #Define StringAlignmentFar  2
         .oStringFormat = Createobject('gpStringFormat')
         With .oStringFormat
            .Create()
            .Alignment = StringAlignmentCenter
            .LineAlignment = StringAlignmentCenter
         Endwith

         * Create a Font object
         Local loFont
         loFont = Createobject("GpFont")

         Local lnFactor, lnMaxWidth
         lnFactor = 0.80
         lnMaxWidth = (Sqrt((.SharedPageHeight ^ 2) + (.SharedPageWidth ^ 2))) * lnFactor

         * To bypass GDI+ MeasureString bug to obtain the correct size
         Local loStringFormat As 'GpStringFormat' Of Home() + 'FFC\_gdiplus.vcx'
         loStringFormat = Newobject('GpStringFormat',Home() + 'FFC\_gdiplus.vcx')
         loStringFormat.Create()
         loStringFormat.GetGenericTypographic()

         Local loSize, lnSize, lnCharsFitted, lnLinesFilled, lnPerc
         lnSize = 1500

         loFont.Create(.cFontName,lnSize,.nFontStyle,2)
         lnCharsFitted = 0
         lnLinesFilled = 0
         loSize = .oGDIGraphics.MeasureStringA(.cWatermark,loFont, ,;
            loStringFormat, @lnCharsFitted, @lnLinesFilled)

         If Vartype(loSize)=="O"
            If loSize.W > lnMaxWidth
               lnPerc = loSize.W / lnMaxWidth
               lnSize = Int(lnSize / lnPerc)
            Endif
         Endif

         loFont.Create(.cFontName,lnSize,.nFontStyle,2)
         .oFont = loFont

         * Calculate the rotation angle
         .nAngle = Rtod(Atan(.SharedPageHeight / .SharedPageWidth ))

         * Create a rectangle with special dimensions
         .oRect = Createobject("gpRectangle", ;
            -.SharedPageWidth/2, -.SharedPageHeight/2, ;
            .SharedPageWidth*2, .SharedPageHeight*2)
      Endwith
   Endfunc
   *
   Function AddWatermark
      With This
         .SetoGDIGraphicsHandle()

         * Prepare transformation
         .oGDIGraphics.TranslateTransform(.SharedPageWidth/2, ;
            .SharedPageHeight/2)
         .oGDIGraphics.RotateTransform(-.nAngle)
         .oGDIGraphics.TranslateTransform(-.SharedPageWidth/2, ;
            -.SharedPageHeight/2)

         * Draw a string
         .oGDIGraphics.DrawStringA(.cWatermark, .oFont, .oRect, .oStringFormat, .oBrush)

         * Reset Rotation
         .oGDIGraphics.ResetTransform()
      Endwith
   Endfunc
   *
   Function SetoGDIGraphicsHandle
      With This
         If Not .IsSuccessor
            .SharedGDIPlusGraphics = .GDIPlusGraphics
         Endif
         .oGDIGraphics.SetHandle(.SharedGDIPlusGraphics)
         .oGDIGraphics.TextRenderingHint = 3 && AntiAlias
      Endwith
   Endfunc
   *
   Function ExtendPreviewContainer
      Local loPreviewContainer
      loPreviewContainer = Null
      Do (_ReportPreview) With loPreviewContainer
      loPreviewContainer.SetExtensionHandler(Newobject("MyExtensionHandler"))
      This.PreviewContainer = loPreviewContainer
   Endfunc
Enddefine

* Create a class that will extend Report Preview
Define Class MyExtensionHandler As Custom
   *
   Procedure Show(iStyle)
      With This.PreviewForm
         With .Toolbar
            * Translate toolbar buttons ToolTips to Brazilian Portugese language
            .cboZoom.ToolTipText = "Zoom"
            .cmdClose.ToolTipText = "Fechar a visualização"
            .cmdGoToPage.ToolTipText = "Ir para a página"
            .cmdPrint.ToolTipText = "Imprimir"
            With .cntNext
               .cmdBottom.ToolTipText = "Última página"
               .cmdForward.ToolTipText = "Próxima página"
            Endwith
            With .cntPrev
               .cmdBack.ToolTipText = "Página anterior"
               .cmdTop.ToolTipText = "Primeira página"
            Endwith
            With .opgPageCount
               .opt1.ToolTipText = "Uma página"
               .opt2.ToolTipText = "Duas páginas"
               .opt3.ToolTipText = "Quatro páginas"
            Endwith
            *
         Endwith
         .WindowState = 2 && Maximize report preview
      Endwith
      DoDefault(iStyle)
   Endproc
   *
Enddefine

To know more about the new VFP 9 reporting system and GDI+, I recomend you to:

  • read VFP 9 help topics: Understanding Visual FoxPro Object-Assisted Reporting and Using GDI+ in Reports;
  • take a look at VFPX website and search for GDIPlusX class that extends GDI+ capabilities;
  • visit César Chalom's blog. He is involved in GDIPlusX project from VFPX team. His blog has great GDI+ samples.

One more time, thanks to César Chalom for develop the code to do the watermark. Congratulations for your great job!

Published Wednesday, September 13, 2006 8:23 PM by emersonreed
Filed Under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: A sample on how to add features to Report Listener

Thursday, September 14, 2006 8:39 AM by Bernard Bout
Emerson

Excellent sample.

But don't stop there please. Let's have more...

# re: A sample on how to add features to Report Listener

Friday, September 15, 2006 10:23 PM by stuartd
Two articles on Reporting in VFP9:

Techniques for alternate Report Previews in VFP 9.0
http://www.spacefold.com/colin/archive/articles/reportpreview/techniques.htm

VFP9: Exploring and Extending Report Preview

http://www.spacefold.com/colin/archive/articles/reportpreview/rp_extend.html

# re: A sample on how to add features to Report Listener

Friday, April 11, 2008 5:15 PM by Cesar
Hi Emerson,

I've been playing with your sample recently, and I think it would be ccol to add the possibility to show or hide the "Print" commandbutton in the toolbar.

It's very simple to add this to your class:

1 - Add a property "PrintFromPreview"

2 - Then, add one single line to the  Function ExtendPreviewContainer, and now it should be like this:

  Function ExtendPreviewContainer
     Local loPreviewContainer
     loPreviewContainer = Null
     Do (_ReportPreview) With loPreviewContainer
     loPreviewContainer.AllowPrintfromPreview = This.PrintFromPreview
     loPreviewContainer.SetExtensionHandler(Newobject("MyExtensionHandler"))
     This.PreviewContainer = loPreviewContainer
  Endfunc


Abraço

Cesar

# How to disable print button in report preview

Saturday, April 12, 2008 10:20 PM by VFP IMAGING
Till now I had seen many samples showing how we can make the Print button invisible from the Report Preview...

What do you think?

(required) 
required 
(required)