many times i have seen where there are grid controls that have an image as their background. now in vfp while it is not too difficult to display images in the grid, you just cannot get the effect as below.


avior:url(#ieooui) }

but with a little ingenuity and some technique this effect as above is certainly possible.

that's where gdi+ comes in. to achieve this you need the gdi+x classes found on vfpx and the imgcanvas class.

create a new class and base it on the imgcanvas class found in gdiplus.vcx.

as you should know, when using the imgcanvas class, you should never put any code in the init. any code you'd normally put in the init should be put in the "setup" method.

the idea to achieve the above effect is to have a transparent image floating above your grid. there is nothing special about the grid. this transparency shows the grid contents below it.

when the user clicks anywhere on the transparent image the click should be transmitted down to the grid at that exact same spot.

the gdi+x is used to display the image as transparent and the ingenuity is what causes the click to travel down.

the class contains some custom properties as below:

ncolour1 and ncolour2 are two colours that will make up the gradient if no image is specified in the picture property.

ntransparency is the amount of transparency you want. i find 25 is a fairly good number with 0 being fully transparent and 255 being opaque.

usepicture if set to .t. will use the picture else will use a gradient based on the two colours.

gridname this is improtant. this is how the class identifies the grid above which it must float, as well as the size it should be. it is important that you enter here the full "path" to the grid since it could verywell be in a container in a page on a page frame.

if so then this property would be:

thisform.mypageframe.page1.mycontainer1.mygrid

and if just placed on a form

thisform.mygrid1

the setup code resizes and positions the imgcanvas control over the grid. it also either uses the image or a gradient with the transparency set. it then displays this.

custom methods

there is a custom method gridmousedown. this code is fired whenever the grid receives a mousedown event. this is achieved by this code in the setup:

bindevent(ogrid,"mousedown",this,"gridmousedown")

but if the imgcanvas is floating over the grid how can the grid get a mousedown event?

that is usually achieved by passing the event down in the mousedown event of the control:

* control.mousedown.

lparameters nbutton, nshift, nxcoord, nycoord

this.ogrid.mousedown(nbutton, nshift, nxcoord, nycoord)

this fires the grid.mousedown which fires our gridmousedown because we are bound to it.

our gridmousedown method has this code:

lparameters nbutton, nshift, nxcoord, nycoord

private lnwhere,lnrelrow,lnrelcol

lnwhere = 0

lnrelrow = 0

lnrelcol = 0

this.ogrid.gridhittest(nxcoord, nycoord, @lnwhere, @lnrelrow, @lnrelcol)

do case

case lnwhere = 1 && column header

case lnwhere = 3 && cell

    this.ogrid.activatecell(lnrelrow,lnrelcol)

case lnwhere = 17 && scrollbar

otherwise

* nothing from hittest

    this.ogrid.when()

endcase

i am using here a very obscure vfp command method of the grid - gridhittest. basically you pass in some variables by refrence and they get filled by the method. check out the help on this.

basically we need to know where the grid received the "hit". once we have that we activate that cell as in the code above.

you will find some idiosyncracy with this control but that cannot be helped.

so to achieve this effect it is as simple as dropping the control on your grid, setting a few properties and voila a grid with a background image when

usepicture = .t.

when usepicture = .f.  we get a gradient.

one more thing i want to mention here. if you select the ncolour1 and ncolour2 properties you get a button to select the colours, just like other vfp colour properties. this is achieved by _memberdata and some extra code as can be see from the following image: as an added bonus here's how to do this with _memberdata.

st1\:*{behavior:url(#ieooui) }

download the gdi+x classes from vfpx as you need them for this.

download the class from the attachment link below. there is a sample form which uses the customer table in the testdata database - c:\vfp9\samples\data\customer.dbf. you need to resolve that to where you have installed vfp. also you will have to resolve the locatuion of where you store gdiplus.vcx

run the sample form, then change the usepicture property and play around with the colours.

unfortunately because of the amount of junk mail being generated from the weblog i have switched off comments. please post your comments, if any, at www.foxite.com

One Response to Decorating a Grid with GDI+

  •  Friday 06 mars 2009
    Hi Bernard
    as i promit you this is my comments on decorating grid :

    0-In the sample form.grid4.scrolled : cut this line
    WAIT WINDOW NOWAIT nDirection

    Left in from my tests

    -splitbar=.f.(prevent expanding panel-left bottom corner of grid)

    1-imgcanvas.beforeDraw

    IF NOT This.usepicture
    loBrush = .Drawing2D.LinearGradientBrush.New(This.Rectangle,.Color.FromArgb(This.nTransparency,This.nColour1),;
    .Color.FromArgb(This.nTransparency,This.nColour2),1)
    loGfx.FillRectangle(loBrush,This.Rectangle)

    —>>can use the 0,1,2,3 gradients types if necessary to various gradients and add a property in class.(look ??)

    2- If the grid.scrollbars=3 (both) the H scrollbar dont work (not include in code of the class).

    In imgcanvas.setUp put this code instead (all cases of scrollbars):
    *******************************
    * size & position it
    oGrid = EVALUATE(This.gridname)
    This.oGrid = oGrid
    LOCAL nVS as Integer, nHs as Integer, nWx as Integer

    do case
    case oGrid.scrollbars=0 &&none
    nVS=0
    nHS=0
    case oGrid.scrollbars=1 &&H
    nHs=sysmetric(8)
    nVS=0

    case oGrid.scrollbars=2 &&V
    nVs=sysmetric(5)
    nHs=0

    case oGrid.scrollbars=3 &&both H+V
    nHs=sysmetric(8)
    nVS=sysmetric(5)

    endcase

    WITH This
    .Top = oGrid.Top + oGrid.HeaderHeight
    nWx = IIF(oGrid.RecordMark,10,0)+IIF(oGrid.deletemark,9,0)
    .Left = oGrid.Left+nWx
    .Width = oGrid.Width -(nWx+nVs)
    do case
    case oGrid.scrollbars=0 or oGrid.scrollbars=2 &&0,V
    .Height = oGrid.Height – (oGrid.HeaderHeight)

    case oGrid.scrollbars=1 or ogrid.scrollbars=3 &&h or h+v
    .Height = oGrid.Height – (oGrid.HeaderHeight)-nHS

    endcase

    **********
    ENDWITH
    * change the grid header colour
    IF NOT This.usepicture
    oGrid.SetAll(“BackColor”,This.nColour2,”header”)
    ENDIF
    * bindit
    BINDEVENT(oGrid,”MouseDown”,This,”gridmousedown”)
    *BINDEVENT(oGrid,”Scrolled”,This,”gridscrolled”) &&imgcanvas dont recover the 2 scrollbars-not necessary
    ****************************************

    4-must precise that PNG transparency is support by VFP9.SP2 only as spoken in forum

    Yes I keep forgetting that only VFP9Sp2 supports PNG when loaded in the PictureVal. So anyone using < Sp2 will not get transparency.

    5-In the imgcanvas.befordraw use the new method
    loBmp.ApplyColorMatrix(loMatrix)
    as Cesar said.

    6-in the demo form
    LPARAMETERS nDirection
    WAIT WINDOW NOWAIT nDirection
    IF nDirection < 2
    ThisForm.Gridtheme4.REFRESH()
    ENDIF
    what is thisform.gridTheme4 ? this property dont exist ?

    Because it is not a property but an object. The theme object that I use is called Gridtheme4 – it is the name of the imgCanvas class used on the form.

    7-Proposition :Can also use the same method to “watermark” with a transparency/picture for ex. an editBox

    Yes I know. I have also done it for a listbox as well. But it does not work properly since there is no GridHitTest method for other controls and the only way to send the click through is to make the image invisible which causes flashing.

    The idea here is not to provide a solurion but to provide an idea of how to think differently. See how much it got you thinking about improvements? And you learnt about some new things eh?

    good luck !

Leave a Reply

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