2007-02-16

NEW GRADIENT BACKGROUND CLASS

After all those posts discussing and showing how to create gradient backgrounds for vfp forms, I finally decided to create a simple but powerful class to ease this process.

The GradBackgrounds class is stored inside the gradientobjects.vcx, the class that was published last year that converts any commandbutton, graphical checkbox or graphical optionbox.

Just drop an instance of the class gradbackgrounds to any form, container or pageframe and set some properties to obtain the gradient effects shown below.

All the background images are created using gdi+, but with no helper class, because I wanted to obtain the best performance possible.

 

properties



 
gradientmode - numeric, from 1 to 4, determines the gradient type to be created
1 - horizontal   2 - vertical   3 - diagonal 1   4 - diagonal 2 using linear gradient
brushes with 2 colors

backcolor1 - numeric, the rgb value of the starting color of the gradient background

backcolor2 - numeric, the rgb value of the destination color of the gradient background

reducecolorlevel - numeric, automatically sets the destination color of the gradient (backcolor2) ranging from 0 (no change) to 100 (white). if left to .f., then no change is applied and the original values of backcolor2 and selbackcolor2 will be used.

updatetabcolor - in the case of a pageframe, sets "themes" off to allow the tab background to be in the same color of the gradient

method
update - updates the gradient if you change any of the above properties

 

form using gradientmode = 1

 

 

form using gradientmode = 2

 

 

form using gradientmode = 3

 

 

form using gradientmode = 4

 

 

playing with pageframes

As containers, pageframes allow to set a picture property. we can also obtain a cool effect changing the tab colors to use the same color of the gradient picture.

To make it work, drop an instance of the class inside every page thet you want to convert to gradient. when inside a pageframe, the property gradient mode becomes automatic, and works according to the 'tabOrientation' property of the pageframe.

 

 

 

The gradient adapts to the "taborientation" property of the pageframe

 

 

 

important notes

To make the class work inside a container, don't forget to set its backstyle to 1 - opaque
Don't forget to set the backstyle property of your labels to 0 - transparent
 


 

vfp9 is cool !

In this version of the class I started using some scripts to ease the manipulation of the properties. For example, now if you double click on the backcolor1 property, the color picker opens automatically, to allow you to choose your color. thanks to the great book "what's new in nine", and some great tips from Fabio Lunardon and Tamar Granor.

 

disclaimer

This class is totally free. The information provided on this page and the source code related to this article comes without any warranty whatsoever. use it at your own risk.

 

some related links

gradient backgrounds in your forms with gdi+

gradient command buttons with gdi+

gradient objects with gdi+ revisited

 

 

download

click here to download the latest version of the gradient objects class.

2007-02-09

Extract icons from EXE, DLL and ICO files with GdiPlus-X

Some types of files allow to store various icons together with other binary data, such as exes and dlls. .ICO files also allow to store more than one icon in a single file. Windows uses this a lot, and stores almost all the icons that it uses all the time in some dll or exe libraries.

The GdiplusX library can easily extract these icons, using the function “ExtractAssociatedIcon” from the xfcIcon class, as follows:

important:

All samples below use the Gdiplus-X library from VFP-X project. Download the latest stable release from codeplex:

http://www.codeplex.com/wiki/view.aspx?projectname=vfpx&title=gdiplusx

 

 

* the following code example demonstrates how to extract icons from an exe file
do locfile("system.app")

local lcfile, lnindex
local loicon as
xfcicon
local lobmp as
xfcbitmap
lcfile =
getfile("exe;ico;dll")
&& _vfp.servername
lnindex = 0
with _screen.system
.drawing
   do while
.t.
      loicon = .
icon
.extractassociatedicon(lcfile, lnindex)
      if isnull
(loicon)
         exit
      endif
      lcNewfile = "c:\" + justfname(lcfile) + transform
(lnindex) + ".png"
      lobmp = loicon.tobitmap()
      lobmp.
save
(lcnewfile, .imaging.imageformat.png)
      lnindex = lnindex + 1
   enddo
endwith
return


The file extracticons.scx in the samples folder brings a form that permits you to select any file, and GdiplusX will draw all associated icons inside an imagecanvas object, like in the picture below:



need more icons ?

In my tests, after I created this function, I was very curious about what icons my computer could be storing inside so many executables and dlls installed, so I created a simple program that will scan through a selected directory, and does a recursive search in all of its subfolders, looking for all the files that can possibly store icons.

To my surprise, lots, really thousands of icons emerged... and very interesting results, I ensure you !

You can try this in your computer too.

Save the program below as howto_extracticonsfromdir2.prg in the help folder of the library. It uses a very cool routine from michael reynolds, that he kindly published in www.fox.wikis.com to obtain the names of all files from the subdirectories. Please note that this will consume some big efforts from your machine, so be prepared to wait about a minute till this task is finished. after running this sample, all the icons will be stored in “c:\myicons\”.

* file : howto_extracticonsfromdir2.prg
* author : VFPIMAGING
* save this file in the help directory in the gdiplus-x library folder
*
* the following code performs the following actions:
*
* asks the user for a path
* creates a cursor containing all available file names (exe, dll and ico)
* from the selected and its subfolders
* scans the cursor and extract all associated icons from each file


* init gdi+
do locfile("system.app")
* create destination directory to receive the extracted icons
lcdir = "c:\myicons\"
if not directory(lcdir)
   mkdir (lcdir)
endif
* create the cursor that will store the valid file locations
create cursor recursive (cfile c(250))

local lccurdrive, lccurdir, lcselecteddir
lccurdrive =
justdrive(fullpath(curdir()))
lccurdir =
curdir()
lcselecteddir =
getdir()
if empty(lcselecteddir)
   wait window "invalid directory"
   return .f.
endif

wait window "retrieving folders information" nowait

* scan through the selected and the subfolders
=recurse(getdir())
chdir &lccurdrive.&lccurdir.
* browse

with _screen.system.drawing
local lcfile, lnindex, lntotrec
local lnoldpercentage, lnpercentage
local loicon as xfcicon
local lobmp as xfcbitmap
store 0 to lnpercentage, lnoldpercentage
lntotrec =
reccount()
scan
lcfile = recursive.cfile
lnindex = 0
do while .t.
loicon =
null
* extract the associated icon
loicon = .icon.extractassociatedicon(lcfile, lnindex)
if isnull(loicon)
exit
endif
lcnewfile = lcdir + justfname(lcfile) + transform(lnindex) + ".png"
lobmp =
null
* send the icon to a gdi+ bitmap object
lobmp = loicon.tobitmap()
if vartype(lobmp) <> "o"
exit
endif
* save the bitmap as png
lobmp.save(lcnewfile, .imaging.imageformat.png)
lnindex = lnindex + 1
enddo
* show progression
lnrec = recno()
lnpercentage =
round((lnrec / lntotrec),1)
if lnpercentage > lnoldpercentage
wait window "extracting icons from files..." + chr(13) + ;
"elapsed: " +
transform(lnpercentage * 100) + " %" nowait
lnoldpercentage = lnpercentage
endif
endscan
endwith
return


*****************************************************************************************
* function : recurse
* author : michael reynolds
* description : good for performing file processing throughout an entire directory tree.
* the function, recurse(), is called with the full path of a directory.
* recurse() will then read all files and directories in the path.
* a function can be called to process files that it finds.
* plus, the function calls itself to process any sub-directories.
*
http://fox.wikis.com/wc.dll?wiki~recursivedirectoryprocessing~vfp
*****************************************************************************************
function recurse(pcdir)
local lnptr, lnfilecount, lafilelist, lcdir, lcfile
chdir (pcdir)
dimension lafilelist[1]
*--- read the chosen directory.
lnfilecount = adir(lafilelist, '*.*', 'd')
for lnptr = 1 to lnfilecount
if 'd' $ lafilelist[lnptr, 5]
*--- get directory name.
lcdir = lafilelist[lnptr, 1]
*--- ignore current and parent directory pointers.
if lcdir != '.' and lcdir != '..'
*--- call this routine again.
recurse(lcdir)
endif
else
*--- get the file name.
lcfile = lower(fullpath(lafilelist[lnptr, 1]))
*--- insert into cursor if .exe, .ico or .dll
if inlist(lower(justext(lcfile)),"dll","exe","ico")
insert into recursive (cfile) values (lcfile)
endif
endif
endfor
*--- move back to parent directory.
chdir ..
endfunc


 

important:

The above procedure shows how to extract the associated icons from some files. Before using those icons in your applications, you first need to make sure you have the rights to do that. Read carefully the eula from those applications prior to using them !

 

I hope you enjoy !

2007-02-06

NEW VERSION OF GPIMAGE2

After some requests, I'm sending a new version of GPIMAGE2, an adapted class from the original GpImage class from Alexander Golovlev.

This new version adds 3 new features to the previous version:
Control smoothing mode, Interpolation mode and a Gradient brush.

Gdi+ originally offers 6 kinds of linear gradient brushes, and many possibilities for path gradient brushes, but to update Gpimage2 is not a priority any more because the GdiplusX library brings much more value, and is compatible with the .NET "System.Drawing" namespace.

So, if you still didn't upgrade to VFP9, you can download this new version, and play with some gradients.

I've included 3 samples that create gradients. you'll find them in the "examples" folder.






brushesgradient.prg   creates some shapes using gradients
gradientform.scx   creates a sample form with gradient effect
gradientform2.scx   creates a sample form with gradient effect, allowing to change the colors and the gradient direction duruing execution

Another new sample, smoothing.scx, from Rafael Lippert, demonstrates how to control the smoothing mode if images.

Enjoy !



GPIMAGE2 gdi+ class

2007-02-05

MSDN COMMUNITY CONTENT

Recently, MSDN added a new and very useful feature to the .net development site, the msdn community content. According to them, "msdn community content provides an infrastructure for users to comment, edit, and add content to the visual studio 2005 and .net framework 2.0 online documentation. (...) anyone can register for the site by signing in with a microsoft passport or windows live id and agreeing to the site terms of use and the participant code of conduct.  anyone who is registered and signed in to the site can create new community content and edit existing community content."

Currently, MSDN provides many sample codes for .net, c#, c++ and j# users. from now on, we hope to add VFP too !

As the new gdiplusx library mimics the "system.drawing" namespace from .net. that means that we can convert codes created for vb .net to vfp very easily. so, i started posting some VFP codes at the "community content" part of some topics.

Have a look at the links below and tell me what you think.

http://msdn2.microsoft.com/en-us/library/system.drawing.drawing2d.graphicspath.clone%28vs.80%29.aspx
http://msdn2.microsoft.com/en-us/library/fz2042a8(vs.80).aspx
http://msdn2.microsoft.com/en-us/library/865tf5y6(vs.80).aspx

Well, better that that, would be if YAG or Milind Lele convinced MSDN people to keep some specific room for some VFP codes for Gdiplus-X directly there :-)

2007-01-29

Send Images to the Clipboard with GdiPlus-X REVISITED

Some days ago I posted a solution based on Alexander Golovlev's GpImage Gdi+ class showing how to send an image to the clipboard.

We agreed that although this function is not present originally on the "system.drawing" namespace from .net, it could represent a good addiction to the gdiplus-x livrary for vfp. so, the function "toClipboard()" was added to the bitmap class.

From now on, I mean from gdiplus-X release 0.07 and forward, we can send any Gdi+ compatible image to the clipboard using the new "toClipboard()" function just added to the bitmap class using the simple code below:

 

** the following code example demonstrates how to send an
** image to the clipboard
do locfile("system.app")
local lobmp as xfcbitmap
lobmp = _screen.system.drawing.
bitmap.new(getpict())
lobmp.toClipboard()

 

 

2007-01-24

IMPORTANT FIX FOR SAMPLES USING GRADIENTS

A strange error occured for some people when using some of the samples for the creation of gradients that I've been providing in this blog.

Some people reported that the original code was creating a black image instead of a gradient. in other cases, the error "cannot load 32-bit dll gdiplus" occured.

This happened because vfp was using different versions of gdiplus.dll installed on the machine. one version to draw the gradient and another version to draw just the gradients. if the machine had only one version of gdiplus.dll installed, even with more than one copy, all went ok. but some applications need a specific version of this library, and ms has already released more than 5 versions till this moment. after a long time testing i detected this using a simple "display dlls" command.

Special thanks to all people that reported this error, tested and helped to find the origin, specially to: Andrew Mcneill, Emerson Reed, Sergey Berezniker, Rui Nogueira, Randy Pearson, Sacchi. I can't forget the more than 70 people from my home, the brazilian foxbrasil community that very kindly tested many codes in different environments.

the fix:
we were using:
declare gdip..... in gdiplus etc etc

The correct is to change from "in gdiplus" to "in gdiplus.dll". on certain machines, this is causing some confusions, and makes vfp use more than one version, specially if the user already uses _gdiplus.vcx or the reportlistener.

Note that vfp declares gdiplus using ".dll" for its internal commands, and also in _gdiplus.vcx

In vfp9's help we can find:
"to ensure that you use the correct copy of gdiplus.dll, use the syntax in gdiplus.dll with no explicit path in your declare dll statements."
http://msdn2.microsoft.com/en-us/library/ms978941(vs.80).aspx

gradobjects class
I've just published the newest version of the class, that can be downloaded from this link. http://weblogs.foxite.com/files/vfpimaging/gradobjects/gradobjects.zip
i also hope to publish a new post explaining all the new features, fixes and samples, but for the moment, this version will help to eliminate the bug.

old posts
I've also updated all previous posts

gradient objects with gdi+ revisited

gradient backgrounds in your forms with gdi+ part2

gradient backgrounds in your forms with gdi+

outlook bar 2003:
The same problem could occur using this tremendous class. to fix it, please open the file outlook2003bar.vcx, select the class "outlook2003bar". sorry emerson !

In method "creategradientimage", please add a ".dll" in the declaration of the gradient gdi+ function, like this:

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


Gdiplusx library
The whole library will receive this update too.
Hopefully, on the next release - 0.07 alpha we'll add this fix and some other features and cool new samples.
http://www.codeplex.com/vfpx/workitem/view.aspx?workitemid=7358

 

All gdiplus declarations:
Craig Boyd has a fantastic post in which he brings all 603 gdi+ declarations.
http://www.sweetpotatosoftware.com/spsblog/permalink,guid,d06cf377-c9ba-4eeb-93aa-b98ac115e895.aspx
They work perfectly, but take care to add a ".dll" after each declaration if you plan to use gdi+ using direct api calls.

2007-01-17

Capture Screens with GdiPlus-X

To capture a screen with Gdiplus-X is a very easy task too.
basically, all we need to do is to call the fromscreen() method from the bitmap class. To ease this task, this method brings some different overloads.

 

important:

All samples below use the Gdiplus-x library from VFPX. Download the latest stable release from codeplex:
http://www.codeplex.com/wiki/view.aspx?projectname=vfpx&title=gdiplusx

 

1 - capture a form screen sending the hwnd of the form or the form as an object 
do locfile("system.app") 

local locapturebmp as xfcbitmap
with _screen.system.drawing
locapturebmp = .bitmap.fromscreen(thisform.hwnd)
* could be also:
* locapturebmp = _screen.system.drawing.bitmap.fromscreen(thisform)
locapturebmp.save("c:\captured.png", .imaging.imageformat.png)
endwith

 2 - capture the whole screen
in this case, no parameter is needed to be passed
do locfile("system.app")

local locapturebmp as xfcbitmap
with _screen.system.drawing
locapturebmp = .bitmap.fromscreen()
locapturebmp.save("c:\capturedscreen.png", .imaging.imageformat.png)
endwith

 

3 - capture the screen of a form cutting off its borders and title.
for this task we use the sysmetric() function to obtain the measure of the screen elements, such as the title height, top and left borders. then we use another overload, sending the hwnd, and the coordinates of the form to be captured.

 
do locfile("system.app")

local lntitleheight, lnleftborder, lntopborder
lntitleheight = sysmetric(9)
lnleftborder = sysmetric(3)
lntopborder = sysmetric(4)

local locapturebmp as xfcbitmap

with _screen.system.drawing
locapturebmp = .bitmap.fromscreen(;
thisform.hwnd, ;
lnleftborder, ;
lntitleheight + lntopborder, ;
thisform.width, ;
thisform.height)

locapturebmp.save("c:\captured.png", .imaging.imageformat.png)
endwith




 

4 - capture all forms in the screen.
this is very simple too. just create a loop through all _screen forms and capture each of them, sending the form.hwnd as a parameter.

 
do locfile("system.app")

local locapturebmp as xfcbitmap
local n
local loform as form
n = 1

with _screen.system.drawing

for each loform in _screen.forms
locapturebmp = .bitmap.fromscreen(loform.hwnd)
locapturebmp.save("c:\capturedform" + transform(n) + ".png", ;
.imaging.imageformat.png)
n = n + 1
endfor

endwith