more than 2 years ago i started blogging on getting vfp to have transparent windows. no, not the fully transparent ones, but the vista like ones, where the window is transparent but the contents, including form objects, are opaque.

this was my first post as proof of concept:

http://weblogs.foxite.com/bernardbout/archive/2006/06/15/1838.aspx

and from proof of concept to the "real" thing http://weblogs.foxite.com/bernardbout/archive/2006/08/16/2261.aspx

with the technique described in detail here http://weblogs.foxite.com/bernardbout/archive/2006/08/27/2353.aspx

an alternate solution without forms - http://weblogs.foxite.com/bernardbout/archive/2006/09/11/2436.aspx 

and finally this long post using 2 forms :

http://weblogs.foxite.com/bernardbout/archive/2006/10/28/2765.aspx

of late i have been playing with the gdi+x classes and this is what i have come up with in the ongoing saga of transparent windows and vfp.

the idea is simple indeed, but needed to be modified to suit the circumstances.i wanted  a mdi form with a background image like wallpaper. the vfp forms would be displayed in  here with a transparent look. because of the technique that i will soon show, this method will only work where you have control of the background and will only work for modal forms.

of course, anyone who has tried the setlayeredwindow api will know that it only works for top level forms and that too the whole form and its contents take on the transparency which gives a horrible effect.

this technique is for child forms of a mdi so they do not need to be top level. however they must be modal. those are the only 2 restrictions to use this technique.

imagine a large image on which you have a rectangular window. you can see through the window to the image behind. and as you move the window over the image, you are able to see different parts of the large image through the window. well my image is my mdi form with a background picture, and my window is my child form.

before it is made visible my child form grabs an image of the complete mdi parent form with any open windows etc. included and then processes this image:

lntitleheight = sysmetric(9)

lnleftborder = sysmetric(3)

lntopborder = sysmetric(4)

* grab an image of the desktop - parent form for storing

with _screen.system.drawing

local lobmp as xfcbitmap

lobmp = .bitmap.fromscreen(thisform.oparent)

the image in memory is then cropped to remove the borders and the titlebar of the mdi form.

* get the rectangle

local lorect as xfcrectangle

* need to take into account the heights of the titlebar and thickness of window borders

lorect = .rectangle.new(;

lnleftborder,;

lntitleheight+lntopborder,;

thisform.oparent.width , thisform.oparent.height)

* remove borders and titlebar from image

local lodestbmp as xfcimage

lobmp = lobmp.clone(lorect)

next the complete image is blurred by getting a thumbnail reduced image and then stretching it back to the original size.

* blurring

local logfx as xfcgraphics

logfx = .graphics.fromimage(lobmp)

* reduce it

local lodestbmp as xfcimage

* change the amount of blur by increasing the 3.

lodestbmp = lobmp.getthumbnailimage(lobmp.width / 3,;

lobmp.height / 3)

logfx.drawimage(lodestbmp, lobmp.getbounds())

the image is further masked by drawing a semi transparent white layer on the blurred image. the white has an alpha value of 140 here, but you can change it for different effects.

* maybe a white "mask"?

local lobrush as xfcbrush

lobrush = .solidbrush.new(.color.fromargb(140,.color.white))

logfx.fillrectangle(lobrush, lobmp.getbounds())

finally the image is saved as a bitmap for use later. it could also be completely done in memory with no disk access using pictureval but in this example of the technique, i save it to disk.

* save it

lcpicture = forceext(addbs(sys(2023)) + sys(3),'bmp')

lobmp.save(lcpicture, .imaging.imageformat.bmp)

endwith

i then add an image object to the form, send it to the back and set the above large image as its picture property.

* add image

thisform.addobject("opic","image")

with thisform.opic as image

.left = 0

.top = 0

.picture = lcpicture

.zorder(1)

.visible = .t.

endwith

in an earlier post  http://weblogs.foxite.com/bernardbout/archive/2008/10/23/7149.aspx 

i showed a funky technique for getting an animation effect in your form background. this technique here is just an extension of that as you will see. the code in the moved event of the form is the same:

lntitleheight = sysmetric(9)

lnleftborder = sysmetric(3)

lntopborder = sysmetric(4)

with thisform.opic as image

.left = -thisform.left - (lnleftborder)

.top = - (thisform.top + lntitleheight+lntopborder)

endwith

what this does is makes the background image of the child form appear to be glued to the borders of the main mdi form, so that the effect we get, is that the background of the child form image object is now a "window" on the large image. since this image is an exact replica of the mdi parent behind the child, it makes our child "window" appear to be transparent!!!

with a bit of blurring and a transparent white mask, the illusion is complete. the child window can be moved around within the mdi form and the illusion is complete. it is for this reason that this only works with modal child forms since opening another window behind the child will not appear in the screen dump taken when the form is first instantiated, spoiling the illusion.

because bmp's are used throughout there is no problem with "flashing". in my earlier tests, using a png gave a huge amount of flashing and so i worked my technique around the bmp format.

the result as you can see is spectacular. move the window around and see that the illusion is complete.

you can see that the form is transparent, but the controls are not. also since this is a form, it behaves exactly like a form. the previous dual window technique caused the activate/deactivate to fire and was a bit laggy when moving the form. the movement in this form is rock solid.

the blurring effect can be seen by looking at the top left of the form shown above, where the text on the tabframe behind is blurred and hazy white. that is the effect of the blurring + white argb mask.

the complete test mdi form with its movable, vista-like child is shown here.

and below is a "normal" vfp form without the added objects.

the only difference in the two forms is the location of the "window" in that the size of the window in the form above is reduced because of the titlebar and borders.

and just by changing the background shape colour of the child window to match the mdi parent's background we "almost" have a sort of theme as shown below.

one more thing i need to mention. hopefully you have noticed the caption on the vista like form. it appears to be semi transparent with a hazy white area backing it. this is as per the original vista forms and aids in readability. that is achieved by gdi+ again and a technique taken from the sample code and used in this post to make glowing buttons.

i have attached all the relevant files below, just extract them and run the form main1.scx. remember that you will also need the gdi+x classes and system.app. get them here:

http://www.codeplex.com/vfpx/release/projectreleases.aspx?releaseid=8606

so whaddya think?

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

3 Responses to Transparent Forms with VFP Revisited with GDI+x

  • Fernando D. Bozzo says:

    Really great! It’s spectacular! Very good work

    Thanks!

  • Sergio says:

    Hi Bernard 🙂
    This looks great !
    Great Work.

    Can this be implemented on ordinary
    modeless form ?

    TIA
    Sergio

    From the blog post:  “Because of the technique that I will soon show, this method will only work where you have control of the background and will only work for Modal forms.”

  • Very Good effect implemented by gdiplusX !Thank you.

    The particularity it runs only on form level=1 (with a background parent fixed form using one image) .

    This is already mentioned in the blog -> It is for this reason that this only works with Modal child forms since opening another window behind the child will not appear in the screen dump taken when the form is first instantiated, spoiling the illusion

    The image who substitutes the “behind the form” make some waves (little perceptible). Not that I notice

    I use form.visible=.f.
    take a capture exact part behind the form
    form.visible=.t.  that makes  a small flash.

    I already know about that – you cannot get the image behind the form without hiding the form and this causes a flash which is why I don’t use it.

    for a top level form (only) i think the best way is to use APIs to make transparent  a choiced color on a top level form (showWindow=2).
    That can be used for not all the form but a particular region colorized on it.


    All that code you posted I already tried years ago. You cannot make a region of the form transparent. You can only make it fully invisible or the whole form , including the objects, gets transparent which I do not want.
     

     

Leave a Reply

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