After reading this post, read also: Gradient backgrounds in your forms with gdi+ part 2
Gdi+ brings us the possibility to create many cool effects such as gradient colors. This feature was not included in _gdiplus.vcx, but can also be accessed easily with a simple call to the flat API. A great part of the codes below that are related to the creation of the gradient brush is from Bo Durban.
To apply this to forms is really easy. add the codes below to the load, resize and destroy events of any form:
load event
LOCAL lcGradFile m.lcGradFile = ADDBS(SYS(2023)) + SYS(2015) + ".bmp" THIS.ADDPROPERTY("cTempGradFile", m.lcGradFile) IF FILE(m.lcGradFile) CLEAR RESOURCES (m.lcGradFile) ENDIF LOCAL lnRgbColor1 m.lnRgbColor1 = RGB(60,30,180) && blue * create gradient image SET CLASSLIB TO HOME() + "ffc/_gdiplus.vcx" ADDITIVE * declare API DECLARE LONG gdipCreateLinebrushI IN GDIPLUS.DLL ; STRING point1, STRING point2, ; LONG color1, LONG color2, ; LONG wrapmode, LONG @linegradient * create a colorobject and store argb color values to variables LOCAL loClr AS gpColor OF HOME() + "ffc/_gdiplus.vcx" LOCAL lnColor1, lnColor2 m.loClr = CREATEOBJECT("gpcolor") m.loClr.FoxRgb = m.lnRgbColor1 m.lnColor1 = m.loClr.ARGB m.loClr.FoxRgb = RGB(255,255,255) && white m.lnColor2 = m.loClr.ARGB * create a bitmap LOCAL loBmp AS gpBitmap OF HOME() + "ffc/_gdiplus.vcx" m.loBmp = CREATEOBJECT("gpbitmap") m.loBmp.CREATE(1,THISFORM.HEIGHT) * get a bitmap graphics object LOCAL loGfx AS gpGraphics OF HOME() + "ffc/_gdiplus.vcx" m.loGfx = CREATEOBJECT("gpgraphics") m.loGfx.CreateFromImage(m.loBmp) * get a gradient brush LOCAL loBrush AS gpBrush OF HOME() + "ffc/_gdiplus.vcx" LOCAL hBrush && brush handle m.hBrush = 0 gdipCreateLinebrushI(BINTOC(0,"4rs") + BINTOC(0,"4rs"), ; BINTOC(0,"4rs") + BINTOC(THISFORM.HEIGHT,"4rs"), ; m.lnColor1, m.lnColor2, 0, @m.hBrush) m.loBrush = CREATEOBJECT("gpbrush") m.loBrush.sethandle(m.hBrush, .T.) * fill the bitmap with our gradient m.loGfx.FillRectangle(m.loBrush,0,0,1,THISFORM.HEIGHT) m.loBmp.SaveToFile(m.lcGradFile,"image/bmp") THISFORM.ADDOBJECT("imgbackground","image") WITH THISFORM.imgbackground .STRETCH = 2 .WIDTH = THISFORM.WIDTH .HEIGHT = THISFORM.HEIGHT .PICTURE = m.lcGradFile .VISIBLE = .T. ENDWITH RETURN
resize event
Thisform.imgbackground.Width = Thisform.Width Thisform.imgbackground.Height = Thisform.Height
destroy event
WITH THISFORM IF FILE(.cTempGradFile) CLEAR RESOURCES (.cTempGradFile) ERASE (.cTempGradFile) ENDIF ENDWITH
New GDI+ classes
The code I presented in the Load event works pretty fine, but sounds really ugly, when comparing to what we are able to do with GdiPlusX
The code below will replace all codes related to the creation of the gradient color in the load event.
* create a GDI+ linear gradient image using GdiPlusX DO LOCFILE("system.app") LOCAL loBmp AS xfcBitmap LOCAL loGfx AS xfcGraphics LOCAL loBrush AS xfcBrush WITH _SCREEN.SYSTEM.Drawing m.loBmp = .BITMAP.New(1, THISFORM.HEIGHT) m.loGfx = .Graphics.FromImage(m.loBmp) m.loBrush = .Drawing2d.LinearGradientBrush.New( ; .Rectangle.New(0, 0, 1, THISFORM.HEIGHT), ; .COLOR.FromRgb(lnRgbColor1), .COLOR.White, 1) m.loGfx.FillRectangle(m.loBrush, m.loBrush.Rectangle) m.loBmp.SAVE(lcGradFile, .Imaging.ImageFormat.bmp) ENDWITH
Related post: Gradient backgrounds in your VFP forms with GDI+ Part 2
Fantastic. I love your blog and your great examples. This is a good one. Too easy!
ReplyDeleteGreat post Cesar. I believe this is one of the first examples using the new GDIPlusX library that has been posted outside of SednaX. You've made my day.
ReplyDeleteHey Thanks Cesar. My question about using RGB colours has been answered by this:
ReplyDelete.Color.FromRGB(lnRGBColor1),
I saw the Method but did not know how to use it.
Also a tutorial on how the xfc classes are instantiated using XFCSystem :
and how the _access events are used to create new objects, etc.
I am totally confused.
Hey Bernard, I'm glad to know it helped you. There's still a lot of work to do in the new classes. But you can easily get great information from MSDN. Their target is to immitate the GDI+ classes from VB .NET. In MSDN and in other links you'll find lots of examples using these classes. Start using the keywords "system.drawing".
Regards
Cesar
Cesar!
ReplyDeleteYes! Another exciting code example! Beautiful!!! For those following this thread, Cesar's technique can also be used to add gradient backgrounds to containers as well.
Obrigado!
Some additional ideas:
1. You can eliminate your Resize() code using VFP 9's awesome Anchor property:
* make following changes to Load method
*!* .Width = Thisform.Width
*!* .Height = Thisform.Height
.Move( 0, 0, Thisform.Width, Thisform.Height )
.Anchor = 15
2. You can eliminate your Destroy() code using VFP 9's not-so-awesome PictureVal property:
* make following changes to Load method
*!* .Picture = lcGradFile
.PictureVal = filetostr( lcGradFile )
delete file (lcGradFile)
The reason I say 'not-so-awesome' is that using the PictureVal property *significantly* slows down form painting during a form resize and, interestingly enough, also seems to display a slightly different appearance than when the image is loaded from file via .Picture.
Anyone have any feedback on why PictureVal performs so poorly and/or a workaround? Intuitively, I would have thought that PictureVal would have been faster than Picture since the image is in memory vs. on disk.
3. If you have a fixed size form (or container!) you can skip the image object altogether and set the form's or container's Picture property directly to the gradient file you generated (lcGradFile).
4. If you're thinking about using this technique in many areas, Cesar's code is perfect for building a self-contained image gradient class that sizes (and anchors) to its parent and whose destroy event automatically deletes the temp gradient file.
A question for you and your audience:
Any ideas on a technique for generating gradients that match XP color schemes? Office 2003 and many 3rd party menu/toolbar components use a technique that generates various types of gradients based on the current XP theme colors. Since all these applications do this consistently, there must be a common technique being used.
If we (VFP community) want to make our applications look like a million dollars then this is the MILLION DOLLAR question :)
Thanks again Cesar!
Malcolm
Thank you all for the kind words.
ReplyDeleteCraig Boyd, you don't need to be so humble, because your and Bo's great work is going to change the lives of VFP users completely. In my honest opinion, after you release the new GDI+ classes, we will be able to tell the world that VFP10 was released. I'm a big fan of you both. You can't imagine how much I've learned just looking at your code. Thank you. Thank you. Thank you.
Hey Malcolm,
ReplyDeleteAll your comments, ideas and fixes are always welcome !
I hope to apply your ideas in my next post.
Regards
Cesar
Cool.
ReplyDeleteHow can I make the gradient be in the diagonal ?
Hi Claudio,
ReplyDeletePls Check this link for diagonal LinearGradientBrushes
http://weblogs.foxite.com/cesarchalom/archive/2006/06/22/1906.aspx
good job ,thanks
ReplyDeletecool!!!!!!!!!!!!!!
ReplyDeleteI try using this codes for making my forms more beautifull, but when i build a executable then it doesnt work, i dont know what else i should do, i just copy and pasted the code in my forms
ReplyDeleteYou probably need to add the library _gdiplus.vcx to your project. What's the error you are getting ?
Versión en Español de este artículo en / Spanish version at http://www.portalfox.com/article.php?sid=2248
ReplyDeleteDear All,
ReplyDeleteI was used this method at my application where i build with vfp 9.0, however this method is running well and smooth if i run the apps with vfp (.pjx)...
The problem is appear when i build my application to executable (.exe)and i put the *.DLL in the same directory with executable file, like gdiplus.dll,mscomctl.dll,msvcr71.dll,vfp9enu.dll,vfp9r.dll,vfp9renu.dll and zdlib.dll. I was distrust the gdiplus.dll file is the root of the problem, but i was tried to copy many kinds size(1.607kb,1.661kb,1.672kb,1.607kb) of the gdiplus file to that directory,the result is same where the colour is grey and can't be change with other colour from GRB setting.
IF after that i run the application (.pjx)from vfp without remove all .dll file the problem still happened,but if i remove all .dll files from that direktory and the application(.pjx) running from VFP,the application is back running normally and i can change the colour.
there is any kinds of solution for my problem? Thanks
Dear All,
ReplyDeleteI was used this method at my application where i build with vfp 9.0, however this method is running well and smooth if i run the apps with vfp (.pjx)...
The problem is appear when i build my application to executable (.exe)and i put the *.DLL in the same directory with executable file, like gdiplus.dll,mscomctl.dll,msvcr71.dll,vfp9enu.dll,vfp9r.dll,vfp9renu.dll and zdlib.dll. I was distrust the gdiplus.dll file is the root of the problem, but i was tried to copy many kinds size(1.607kb,1.661kb,1.672kb,1.607kb) of the gdiplus file to that directory,the result is same where the colour is grey and can't be change with other colour from GRB setting.
IF after that i run the application (.pjx)from vfp without remove all .dll file the problem still happened,but if i remove all .dll files from that direktory and the application(.pjx) running from VFP,the application is back running normally and i can change the colour.
there is any kinds of solution for my problem? Thanks