2006-07-11

GRADIENT COMMAND BUTTONS WITH GDI+

This is a deprecated post. Please search in this blog for the next posts, for the improved gradient objects and background classes.

 

Using some of the techniques presented in my previous posts, (read gradient backgrounds in your forms with gdi+), I've created a very simple subclass of the commandbutton object, in order to create gradient background effects.

Please take note that this is an unfinished class, not to be used in production. I'm posting it here at this moment to show to people that we can obtain very cool effects using gdi+.

This is how the form looks in development mode:

1000.107.1970.GradDev

 

Below you can see the form running, when gdi+ creates the backgrounds.

1000.107.1971.GradRun

 

properties that you need to fill to have the desired results:

caption, fontbold, fontunderline, fontitalic, fontstrikethru

picture,

backcolor (with the main color to be used as background)

gradientmode (0 = no gradient 1 = vertical-default 2 = horizontal 3 = diagonal1 4 = diagonal2)

 

how the class was created:

I used the commandbutton base class, to make it have the most common usage and understanding possible, making the development mode the most seemed to the result obtained when running the form.

In the init event of the class, it verifies the gradient direction, and creates a lineargradient brush, using the color defined in the backcolor property of the object. The second color was set to white as default. Then it draws a rectangle using this brush in a picture just created, that has the same dimensions of the commandbutton.

The next step is to check if there is a picture assigned to the button; if yes, draw it to the left side, centered in the vertical.

If the caption property was set, then draw the string, centered in horizontal and vertical.

In this example i'm only using gifs with transparent background, so that the background is preserved..

 

the codes

The main code stays in the init event of the commandbutton subclass:

with this

local lcgradfile, lngradmode, lngradpixels, x1, y1, x2, y2, lnwidth, lnheight
lngradmode = .gradientmode
if lngradmode = 0
return && no gradient background !
endif

lcgradfile = addbs(sys(2023))+sys(2015)+".bmp"
.ctempgradfile = lcgradfile

local lcpicture, lccaption, lnrgbcolor1
lcpicture = .picture
lccaption = .caption
lnrgbcolor1 = .backcolor

lnwidth = .width
lnheight = .height

do case
case
lngradmode = 1 && vertical
y1 = 0
x2 = 1
y2 = lnheight
case lngradmode = 2 && horizontal
y1 = 0
x2 = lnwidth
y2 = 1
case lngradmode = 3 && diagonal topleft -> bottomright
y1 = 0
x2 = lnwidth
y2 = lnheight
case lngradmode = 4 && diagonal bottomleft -> topright
y1 = lnheight
x2 = lnwidth
y2 = 0
endcase

* create gradient image
set classlib to home() + "ffc/_gdiplus.vcx" additive

* create a colorobject and store argb color values to variables
local loclr as gpcolor of home() + "ffc/_gdiplus.vcx"
local lncolor1, lncolor2
loclr = createobject("gpcolor")
loclr.foxrgb = lnrgbcolor1
lncolor1 = loclr.argb
loclr.foxrgb = rgb(255,255,255) && white
lncolor2 = loclr.argb

* create a bitmap
local lobmp as gpbitmap of home() + "ffc/_gdiplus.vcx"
lobmp = createobject("gpbitmap")
lobmp.create(.width, .height)

* get a bitmab graphics object
local logfx as gpgraphics of home() + "ffc/_gdiplus.vcx"
logfx = createobject("gpgraphics")
logfx.createfromimage(lobmp)

* declare api
declare long gdipcreatelinebrushi in gdiplus.dll ;
string point1, string point2, ;
long color1, long color2, ;
long wrapmode, long @linegradient

* get a gradient brush
local lobrush as gpbrush of home() + "ffc/_gdiplus.vcx"
local hbrush && brush handle
hbrush = 0
gdipcreatelinebrushi(bintoc(0,"4rs") + bintoc(y1,"4rs"), ;
bintoc(x2,"4rs") + bintoc(y2,"4rs"), ;
lncolor1, lncolor2, 0, @hbrush)

lobrush = createobject("gpbrush")
lobrush.sethandle(hbrush, .t.)

* fill the bitmap with our gradient
logfx.fillrectangle(lobrush,0,0,.width, .height)

* draw the desired picture
if not empty(lcpicture)
local lopict as gpimage of home() + "ffc/_gdiplus.vcx"
lopict = createobject("gpimage")
lopict.createfromfile(lcpicture)

x1 = 1
y1 = (.height - lopict.imageheight) / 2
logfx.drawimageat(lopict,x1, y1)
endif

* draw the caption
#define fontstyleregular 0
#define fontstylebold 1
#define fontstyleitalic 2
#define fontstyleunderline 4
#define fontstylestrikeout 8

#define unitworld 0
#define unitdisplay 1
#define unitpixel 2
#define unitpoint 3
#define unitinch 4
#define unitdocument 5
#define unitmillimeter 6

if not empty(.caption)
local lnfontstyle
lnfontstyle = fontstyleregular + ;
iif(.fontbold, fontstylebold, 0) +;
iif(.fontitalic, fontstyleitalic, 0) +;
iif(.fontunderline, fontstyleunderline, 0) +;
iif(.fontstrikethru, fontstylestrikeout, 0)

local lofont as gpfont of home() + "ffc/_gdiplus.vcx"
lofont = newobject('gpfont', home() + 'ffc/_gdiplus.vcx')
lofont.create( .fontname ; && font name
, .fontsize ; && size in units below
, lnfontstyle ; && fontstyle
, unitpoint ) && units

* create solidbrush with the forecolor
local losolidbrush as gpsolidbrush of home() + "ffc/_gdiplus.vcx"
losolidbrush = newobject('gpsolidbrush', home() + 'ffc/_gdiplus.vcx','',0)

loclr.foxrgb = .forecolor
losolidbrush.brushcolor = loclr

* measure the height of the caption to calculate vertical position
local lostringsize as gpsize of home() + 'ffc/_gdiplus.vcx'
lostringsize = logfx.measurestringa(.caption, lofont)

lnpictwidth = iif(empty(lcpicture), 0,lopict.imagewidth)
x1 = lnpictwidth + ((.width - lnpictwidth - 1) - lostringsize.w) / 2
y1 = (.height - lostringsize.h) / 2

* create pointf with the position of caption
lctextpoint = bintoc(x1,'f') + bintoc(y1,'f')
logfx.drawstringa(.caption, lofont, lctextpoint, , losolidbrush)
endif

* save image to file
lobmp.savetofile(lcgradfile,"image/bmp")

.picture = lcgradfile

endwith
return

 

In destroy event, we just delete the temporary image created

if this.gradientmode = 0
return && no gradient background !
endif

with this
if file
(.ctempgradfile)
clear resources (.ctempgradfile)
erase (.ctempgradfile)
endif
endwith

 

to be improved:

- pictureposition - at this moment, it will always work as "1 - left of caption, centered relative to caption". vfp9 brings 14 position options, this can be done easily in a future version.

- add another property to receive the 2nd color ( at this moment, white - rgb(255,255,255) is default)

- permit to create 3 color gradients, allowing for example: blue - white - blue

- to deal with a disabled commandbuttons. please send suggestions / or pictures showing how the control should look when disabled !

- permit to receive any image, and create the transparency of the backgrounds.

 

The icons that i used to create this example were taken from http://www.iconbazaar.com , where you can find many cool gifs

 

07/19/2006 - updated version of the class

I've received many suggestions, and created a new version of the class, adding many other features.

You can download the most recent version of the class and some forms using it from this link :
http://weblogs.foxite.com/files/vfpimaging/gradobjects/gradobjects.zip

When running the form "testgradbuttons", please pass the mouse over the buttons and also click the "disable" button.