after some testing and additional functionality programmed in, i have decided to release this new version of the gdi+x pad - v1.35.

there are a number of enhancements to it, to enable it to be easier to use, which i will list here:

1. the error handler was changed to the older conventional on error from the try...catch style because try...catch was unable to process certain errors and threw up nesting errors. the error handler now handles improper code statements correctly.

2.the image canvas has some additional functionality.

if you move your mouse over the canvas, a white border appears. if your mouse is at any of the edges, the mouse changes to "sizer" icons and you are now able to grab that edge of the canvas and resize it or move it. above is an image of the new canvas sized. also there is some text that shows the current width and height of the canvas, which will assist when designing on your own form.the new size and location are now "sticky" for that code tab.

to see how this works, load the chess board snippet and click refresh to update the canvas.

now move your mouse over its edges and resize it. the canvas will be automatically refreshed when you release the mouse button after resizing. note that the new dimensions are displayed above.

3. below the canvas, is the code editing window. this area too has some additional functionality. in the form of multiple tabs.

you can now have more than one snippet open at a time and work on it. this facilitates the copying and pasting between open windows easily.

you just click the large red "plus" sign to add a new tab. you can have a maximum of 7 tabs open at one time. now you can load a different snippet into different tabs and switch between tabs easily. un needed tabs can be closed by moving the mouse over the "x" which highlights to red and clicking.

clicking this area will close the tab with a warning to save.

4. because a prg window was being used to edit code, copy, paste and other editor keyboard shortcuts were not working. this has now been fixed and you have access to copy, paste, cut, undo, redo, select all using the standard keyboard shortcuts.

5. minor changes were made to the chart screen to make it a bit clearer about its usage.

since i still have a few enhancements which i want to incorporate, i have not yet released the source. however the updated files can be downloaded from the link below as usual.

the big question is - how is this application useful in helping me design objects using gdi+x?

a short walkthru of a real life example should show the usefulness.

walkthrough - creating a gradient button with gdi+x pad.

1. start up gdi+x pad and load and run the new gradient button sample. 

2. you should see a screen like the one below:

3. hover the mouse over the canvas edges and resize the canvas so that it resembles the size of a normal button as below. note the width & height:

we now have our button sized to 146x42 pixels. however the font size is too big for this size button so in the code window go to this line of code (see below) and change the second parameter to 16 to make the font size 16. you could also change the font name and other properties but for this example, just change the font size from 48 to 16 and refresh (f5)

you will find that the button looks more correct now.

there is one line of code i will explain here:

path3 = this.getpath(this.rectangle,30)

there are no built in functions in gdi+ to get rounded corners for a square or rectangle. in the canvas, i have added a function to give rounded corners, that i have used in other classes. the method is getpath()

this requires at least 2 parameters (3 optional) and these are :

1. the rectangle to act upon - in out case it is the whole canvas

2. the amount of curvature to apply to the corners as an integer.

3. the third parameter is optional, but you can pass a 0,1 or 2.

  • 0 - all 4 corners are rounded
  • 1 - only the top 2 corners are rounded
  • 2. only the bottom 2 corners are rounded.

from the code above and the resultant image you can see that a curvature of 30 is too much for a small button. so change the code to read:

path3 = this.getpath(this.rectangle,15)

and after refresh you get the button now looking like this:

if you prefer you can change the curvature to 5 to get a very subtle change as shown below:

in fact i prefer this curvature of 5.

similarly the other sections of code can be changed like the colours, font attributes etc. once you are happy with the result you can create a new snippet and save the code to that snippet. or you can save the code to a disk file or even copy it to the clipboard.

4. now in vfp you only need to open a new form and drop the imgcanvas class from the gdiplus.vcx class on the form.

open the imgcanvas.beforedraw method and paste this code you created in the steps above.

size the imgcanvas object to the dimensions you had for the canvas object (146x42)

5. you will need to add a new method to the form oe imgcancas object if subclassed, called getpath and paste the following code into it:

lparameters rc,r,ncurvetype

* ncurvetype - 0 full curve, 1 top only, 2 bottom only

* rc = the rectangle

* r = the amount of curve

if empty(ncurvetype)

    ncurvetype = 0

endif

local x,y,w,h,xpath,rx

x = rc.x

y = rc.y

w = rc.width

h = rc.height

rx = r

ry=r

do case

case ncurvetype = 1

    * top only

    rx = 1

case ncurvetype = 2

    * bottom only

    ry = 1

endcase

with _screen.system.drawing

    xpath = .drawing2d.graphicspath.new()

    xpath.addarc(x, y, ry, ry, 180, 90) && upper left corner

    xpath.addarc(x+w - ry, y, ry, ry, 270, 90) &&upper right corner

    xpath.addarc(x+w - rx, y+h - rx, rx, rx, 0, 90) &&lower right corner

    xpath.addarc(x, y+h - rx, rx, rx, 90, 90) &&lower left corner

    xpath.closefigure()

endwith

return xpath

also your pasted code should call this method(form method)

path = thisform.getpath(this.rectangle,curvature)

or if sub classed and a method added:

path = this.getpath(this.rectangle,curvature)

6.  now if you run your form you will get a similar button. you can change the code like the button text etc. to your satisfaction or better yet just open your snippet in the gdi+x pad, and make the changes there, test and when satisfied, copy and paste it into your own class.

note: the size and location attributes are not saved with the sample code - yet.

radek strouhal reported an error on running the file. i traced this to a corrupt index file. i have updated the zip below. please test and let me know.

download the latest update from the link below and don't forget that you need foxtools.fll as well as system.app from this link(now updated).

Download

4 Responses to GDI+X Pad gets an update with added functionality and tutorial

  • boudewijn lutgerink says:

    Cool tool, Bernard.

    Thanks BL.

  • Willianto says:

    Looks great, Bernard…. I’m downloading this and looking forward to try it. Seeing the interface (without the CodeWind), I find it hard to believe that it is created with VFP. 🙂

    Thanks for sharing.

  • Grover Cox says:

    I have known about GDI+ for a long time, and you blog and VFP examples have opened my eyes to the power of GDI+. I have a information request. Awhile back I saw some entries on how to create Irregular Shaped objects. And I can no longer find them. My need is to create clickable objects (for a VFP app) that might be in any shape, ie. Hand with fingers, shoulder, foot, and other body objects, for a Chiropractic application. The existing VFP objects (Image, button etc) are all squares or circles which will not meet this need.
    Can you help me find what I need to meet this requirement? Hopefully GDI+ will be the base part of the solution since this is a large VFP9 application!

    Thanks for your help and keep up your great work.

    Grover Cox
    Stockbridge, GA USA

    • Bernard Bout says:

      Grover
      You’d be better off using PNG images with transparency, inserted into an Image control. Less overhead and very easy to do since the Image control has a CLICK() event.

Leave a Reply

Your email address will not be published. Required fields are marked *