Foxite.COM Community Weblog

Foxite.COM Community Weblog - free weblog service for the Visual FoxPro Community.
Welcome to Foxite.COM Community Weblog Sign in | Join | Help
in
Home Blogs Forum Photos Forum Archives

VFP IMAGING



Direct Draw with the Image Canvas from GdiPlus-X

One of the most interesting additions that the GdiPlusX library brings is the ImageCanvas object. It’s a subclass of the VFP’s original image object, that allows to draw directly on the image object using the graphics commands from GDI+ without accessing the disk. It renders images super fast, and brings many new possibilities for VFP users.

The ImageCanvas class permits rendering graphics on a VFP form, bringing the possibility to draw directly to a VFP Image control, instead of drawing using the form’s HWnd. This way developers don’t need to worry about the Windows Paint updates. It works super fast ! Images are stored in memory, avoiding disk access and performance loss.

Basically, the created image is saved to a stream. Streams are similar to standard files but they are stored in the memory. The image is retrieved from the memory, and stored in the PictureVal property of the Image object.

In this short tutorial I'll show how you can draw directly to the Image object, taking benefits from Intellisense. At the end of the sample code you'll find some code that shows how you can save the just created image to a file, and print it !

 

IMPORTANT:

All samples below use the new GDIPlus-X library, that is still in ALPHA version, but is already stable and reliable to do the majority of GDI+ tasks. Download the latest stable release from Codeplex:

http://www.codeplex.com/Wiki/View.aspx?ProjectName=VFPX&title=GDIPlusX

 

Properties

oGfx The GDI+ Graphics object that we will use to direct draw on the canvas
oBmp The Bitmap object associated to this canvas
Rectangle Returns a GDI+ rectangle object with the dimensions of this ImgCanvas

Some other secondary properties available that deal directly with the Graphics object, like: InterpolationMode, RenderMode, SmoothingMode and TextRenderingHint. You can find some complete information about these on MSDN.

Methods

BeforeDraw Here you will place all codes that will create your image.
Draw Call this method to make the ImageCanvas execute the code placed in “BeforeDraw”. Have in mind that this method is fired when the ImgCanvas is initialized.
AfterDraw Method is executed after the Draw method is finished

   

Below is a simple tutorial showing how you can work with the ImageCanvas:

1 - Create a new form, “TestCanvas.scx”

2 - Open the Project Manager of the latest GdiPlusX library, select the “Classes” tab, expand “GdiPlusX”, selecting the ImgCanvas Object

3 - Drag and Drop the “ImgCanvas” object to the form.

4 - DoubleClick on the image object, select the “BeforeDraw” method.

5 - To make our drawings easier, let's enable Intellisense for the Graphics - oGfx - Property of the Image Canvas.

Now, start adding some code:

WITH _Screen.System.Drawing
* To allow Intellisense for "This.oGfx"
Local loGfx As xfcGraphics
loGfx =
This.oGfx
 
* Test Intellisense for "This.oGfx"

* Type letter by letter the text below:
loGfx.
 

This simple trick will bring Intellisense to us every time that we will type “loGfx.”

 

I also strongly recommend that you have a look at this previous post, that shows some other Intellisense tips when working with the GdiPlus-X library, "Be more productive with GdiPlus-X".

6 - Now let’s add some code to the “BeforeDraw” method to see our Canvas in action (you can see immediately each part of code the resulting image that was created):

 

Copy and paste the code below to the BeforeDraw() method of the Image Canvas:

 

WITH _Screen.System.Drawing
* To allow Intellisense for "This.oGfx"
Local loGfx As xfcGraphics
loGfx =
This.oGfx
 
* Create a Linear Gradient Brush
Local loGradBrsh As xfcLinearGradientBrush
loGradBrsh = .Drawing2D.LinearGradientBrush.New(;
This.Rectangle, .Color.LightBlue, .Color.DarkBlue, 1)
* Draw a rectangle using the whole rectangle from the canvas and the Gradient Brush
loGfx.FillRectangle(loGradBrsh, This.Rectangle)


 
* Draw a Triangle
Dimension laPoints(3)
laPoints(1) = .
Point.New(20, 100)
laPoints(2) = .
Point.New(90, 100)
laPoints(3) = .
Point.New(55, 40)
loGfx.FillPolygon(.Brushes.Green, @laPoints)

 


 
* Draw two Rectangles
loGfx.FillRectangle(.Brushes.Yellow, 20, 100, 70, 50)
loGfx.FillRectangle(.Brushes.Gray, 90, 100, 100, 50)

 

 


* Draw a Trapeze
Dimension laPoints(4)
laPoints(1) = .
Point.New(55, 40)
laPoints(2) = .
Point.New(90, 100)
laPoints(3) = .
Point.New(190, 100)
laPoints(4) = .
Point.New(155, 40)
loGfx.FillPolygon(.SolidBrush.New(.
Color.FromRGB(128,0,0)), @laPoints)

 

 

* Create a path containing two curves
Local myPath As xfcGraphicsPath
myPath = .Drawing2D.GraphicsPath.New()
myPath.StartFigure()
Dimension points(4)
points(1) = .
Point.New(45, 150)
points(2) = .
Point.New(65, 170)
points(3) = .
Point.New(45, 190)
points(4) = .
Point.New(65, 210)
myPath.AddCurve(@points)
myPath.AddLine(.
Point.New(65,210), .Point.New(85, 210))
points(1) = .
Point.New(85, 210)
points(2) = .
Point.New(65, 190)
points(3) = .
Point.New(85, 170)
points(4) = .
Point.New(65, 150)
myPath.AddCurve(@points)
myPath.AddLine(.
Point.New(65,150), .Point.New(45, 150))
* Draw the path
loGfx.FillPath(.Brushes.Orange, myPath)
loGfx.DrawPath(.
Pen.New(.Color.Black, 1), myPath) && Black Border

 


* Draw the Sun
Local loPath As xfcGraphicsPath
loPath = .Drawing2D.GraphicsPath.New()
loPath.AddEllipse(280, 20, 40, 40)
Local loPathGradBrush As xfcPathGradientBrush
loPathGradBrush = .Drawing2D.PathGradientBrush.New(loPath)
loPathGradBrush.CenterColor = .
Color.Red
loPathGradBrush.SurroundColors[1] = .
Color.Yellow
loGfx.FillEllipse(loPathGradBrush, 280, 20, 40, 40)
 

 

 

* Draw a string
loGfx.DrawString("GdiPlusX is cool !!!", ;
.
Font.New("Tahoma", 20), .Brushes.Red, 110, This.Height - 40)


 


* Save the Image to Disk
This.oBmp.Save("String.png", .Imaging.ImageFormat.Png)
* Print the Image
This.oBmp.ToPrinter()

ENDWITH

 

Run the form to see the output from the above code:

 

There are lots of things that you can do with the canvas. Almost all the samples from the GdiPlus-X library use the ImageCanvas object, due to all the facilities it brings for drawing. 

After you understand how it works, drawing with GDI+ will be just like cutting a piece if cake !

Published Tuesday, March 20, 2007 5:03 AM by cesarchalom
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

 

Franklin Garzón said:

Great, VFP are cool for ever.
March 20, 2007 2:14 PM
 

Bernard said:

So you have finally cracked it. Congratulations.

I pasted your code into the form method. All the objects draw except the path with 2 curves. I get an Error at this line

myPath.AddCurve(@points)

Unhandled Structured Exception. Error No. 2071
Message: User Thrown Error
UserValue: (Object)

Other than that it works fine. Now I will study this code more.

Thanks.

Hi Bernard,

>> So you have finally cracked it. Congratulations.

Nope ! There's no crack at all here. We've been using the Image Canvas for months. 99% of the sample forms from the library already use this feature. One of the few things that is still missing in the library is the Stream class. At this moment, the ImageCanvas uses streams, but with direct API calls. After we deliver the Stream classes the ImgCanvas will be modified to use it, but the functionality will be the same, and users won't see any difference.

I see you've been curious about saving images to the memory. I've done some tests, using some different aproaches, and I hope to post soon about this.

I'm sorry about the bug... That's probably because I'm using a fresher version of the library. Me and Bo are used to upload some "planned for future releases" at Codeplex. Please visit http://www.codeplex.com/VFPX/Release/ProjectReleases.aspx?ReleaseId=1711 and download the file GdiPlusX_20070205.zip

Then, please run the sample again, making sure to be working with the latest version of the library.

I'm really sorry for the inconvenience, and hope to have your feedback soon !

Cheers

Cesar

March 21, 2007 2:29 AM
 

Cesar Chalom said:

 
According to Wikipedia, "In typesetting, justification (can also be referred to as 'full justification')...
March 31, 2007 3:14 PM
 

Cesar Chalom said:

Since the latest version, GdiPlusX offers many different ways to manipulate images with no disk access....
November 7, 2007 5:22 AM
 

Cesar Chalom said:

Since the latest version, GdiPlusX offers many different ways to manipulate images with no disk access....
November 7, 2007 5:24 AM

What do you think?

(required) 
(optional)
(required)