Sunday, July 11, 2004

Enhance VFP9 Report using GDI+

During this weekend, I have came up a simple sample that enhance VFP9 report using GDI+, by refering couple of resources, such as GDI+ on MSDN library, www.News2News.com, FoxProAdvisor and helps from UT members especially Lisa Nicholls and Anatoliy Mogylevets.
Some wrapper classes and methods are implemented. It does not cover all of GDI+ functions, only those used in this project. It would take quite long time to implement all of them. Therefore, it would be good if FoxTeam could provide GDI+ wrapper classes, since they should be more familiar with GDI+ functions.

During this VFP9 Report project, I was stuck on couple of places which I think should be pay attention on:

1. Don't call GDI+ cleanup code while graphics object killed (GdiplusShutdown & GdipDeleteGraphics) if you are using GDI+ graphic handle from VFP report for drawing. Otherwise, your report will hang.

2. GDI+ use ARGB (Alpha, Red, Green, Blue) color value instead of RGB. I have wrriten color class to handle the conversion.

3. Some GDI+ API GdipFillRectangle doesn't work for me. I got to use GdipFillRectangleI instead. The difference between both functions is GdipFillRectangleI receive coordinate parameter as INTEGER, but GdipFillRectangle receive REAL. I used to change my data type to LONG in API declaration, but doesn't help.

4. Function GdipDrawLineI works fine in drawing non-straigt line.
x1 = 100

y1 = 175
x2 = 500
y2 = 176
But not horizontal or vertical line.
x1 = 100

y1 = 175
x2 = 500
y2 = 175

= GdipDrawLineI(x1, y1, x2, y2)
if anyone has any ideas, pls comment.

Back to the sample. This sample generate student exam score report, displaying student score field by text and graphically (thermometer). [Screenshot]

Here is the code in ReportListener.Render()
LPARAMETERS nFRXRecno, nLeft, nTop, nWidth, nHeight, ;

nObjectContinuationType, cContentsToBeRendered, ;
GDIPlusImage

LOCAL loGraphics, loColor, loSolidBrush, loPen, lnScoreWidth

THIS.setFRXDataSession()

SELECT frx
GO (nFRXRecno)

*-- I have keyed in "CHART" in Rectangle control's user column
*-- to indicate that is the control used for drawing purposes.
*-- Check if it is the border we want
llChart = frx.User = "CHART"

this.setCurrentDataSession()

IF llChart
loGraphics = CREATEOBJECT("Graphics")

*-- Set report GDI+ handler to custom graphics class
loGraphics.GetFromExternal(THIS.GDIPlusGraphics)

*-- Get color ARGB value from color class
*-- Red color is used in this sample.
loColor = CREATEOBJECT("Color", 255,255,0,0)
loPen = CREATEOBJECT("Pen", loColor.Color, 4)

loSolidBrush = CREATEOBJECT("SolidBrush", loColor.Color)

*-- Draw thermometer rectangle border
loGraphics.DrawRectangle(loPen.Pen, nLeft , nTop , ;
nWidth , nHeight )

*-- Calculate the width thermometer value bar width
lnScoreWidth = (Exam.Score / 100 * nWidth)

*-- Fill color into rectangle but adjust the position and ;
*-- reduce size from original one to have special effect.
loGraphics.FillRectangle(loSolidBrush.SolidBrush, ;
nLeft + 20 , ;
nTop + 20 , ;
lnScoreWidth - 40, ;
nHeight - 40)

STORE .NULL. TO loSolidBrush, loColor, loGraphics
NODEFAULT
ELSE
DODEFAULT(nFRXRecno, nLeft, nTop, nWidth, nHeight, ;
nObjectContinuationType, cContentsToBeRendered, ;
GDIPlusImage)
ENDIF


Click here to download the full sample, for those whose interested.

[NOTE: It is a test program. Run / use this program at your own risk.]

0 Comments:

Post a Comment

<< Home