Welcome to Foxite.COM Community Weblog Sign in | Join | Help

Bernard Bout

May the Fox be with you...

<July 2010>
SuMoTuWeThFrSa
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

Post Categories

News

site statistics

Locations of visitors to this page

Navigation

Some VFP links

Others...

Archives

Who links to this site?

Hey There!!!

Syndication




Ultra Simple Buttons with GDI+X + Icons
I published some ultra simple buttons a while back that were quite lightweight
These had only text and the text was centrally aligned.

Since then I have had requests to include the ability to add an icon and so these buttons have been enhanced to include icons as well as Text alignment.

Two new properties have been added to the Favourites tab to allow this:

1. New property - Textalignment

0 - Middle (Default)
1 - Left
2 - Right

2. New property - Buttonicon

If set to an image (bmp, gif, png,jpg) it will display a 24x24 pixel image on the button. If Textalignment = 1 then image is shown on the right otherwise on the left of the button. Make sure your image has a white background as the class will make the white parts in the image transparent.

3. If property Caption is EMPTY and Buttonicon points to an image, then the button drawn with image in the centre.

For usage and setting other properties please refer to the original link for the buttons.

The sample form attached shows the buttons "in action" and also contains the new updated class.

Again, please download the original button archive where I have included the updated gdiplusx files to avoid any flashing or "x" boxes appearing, and make sure these buttons point to this new gdiplusx class only.

Download the attachment below for the updated button class.


posted Tuesday, April 06, 2010 1:14 PM by bbout | 3 Comments
Filed Under:
Attachment(s): UltraSimpleBtnWithIconV1.zip

Ultra Simple Buttons with GDI+X
Not another set of buttons you might say. Actually I developed these buttons for a POS app a while back and finally got round to posting them.

The buttons are simple to use with all properties you need to set in the Favourites tab.

oFontName - The name of the font to use
lShowBell - This gives a bell shape to the gradient. Basically it changes the style of the button. See the image below.

nButtonColour1
nButtonColour2 - The 2 colours that will be used for the button when
nButtonType = 4. Use the colour picker to change these.

nButtonType - There are 4 pre defined colours but you can add your own :
0 - Black/Grey
1 -  Blue
2 - Orange
3 - Green
4 - Uses the custom colours you set.

nFontColour & nFontSize are self explanatory.

For all colours use
the colour picker to change these.

Here is the sample form with the buttons as they would look with the different options.



These buttons give visual feedback to the user. The colour gradient is flipped when the mouse moves over them. Also if the button is clicked, there is slight movement so the user knows that the button was clicked.



Important Note: You need the system.app of the GDI+X from Codeplex. However I have included a modified version of the gdiplus.vcx class that should be used with these buttons.

In fact it would be better if you used this class instead of the one from Codeplex as it solves a problem with that class.

If there are many buttons placed on a form then when the form first displays, you see a rectangle and "x" where each button is before the buttons are drawn. With the class included in the download this problem does not exist since the form is only displayed after all buttons are drawn so you never see any "X"

Enjoy.

posted Wednesday, March 17, 2010 1:45 PM by bbout | 3 Comments
Filed Under:
Attachment(s): UltraSimpleButtons.zip

The Fastest Lightbox Ever
In one of my previous posts I described a Lightbox class that was Activex friendly.
The old post is here: VFP Lightbox Class - Now Activex Friendly

Unfortunately because of the logic used in the class, for large "busy" forms with a large number of objects, it caused a couple of seconds delay before the lightbox was displayed and even then on slower computers the screen update was noticeably slow.

So I had another look at the logic of the previous version and threw away most of the code. The result is a lean, mean lightbox that is very snappy to display. It now uses only the GDI+X imgCanvas class exclusively for its display.

To ensure speed the following must be observed:
  • The class will only work on a form. It will not support any other containers
  • It requires the GDI+x Libraries (system.app and GDIPLUS.VCX/VCT)
  • It IS however,Activex friendly
To use it is simplicity itself as shown in the sample form.
Just drop the class on a form and call it as shown.

LPARAMETERS tcMsg
LOCAL lRet as Boolean
ThisForm.bbgdilightbox1.ShowLightbox(.T.)
IF MESSAGEBOX(tcMsg,292,"Are you sure?",0) = 7
    lRet = .F.
ELSE
    lRet = .T.
ENDIF
ThisForm.bbgdilightbox1.ShowLightbox()
RETURN lRet






In the control.BeforeDraw() method you will find some code like this:
* change the colours as needed here
* possible colours are (220,128,0,0),(220,0,0,128) etc.

        loBrush = .SolidBrush.New(.Color.FromArgb(220,0,0,0))

These are ARGB where the first number denotes the opacity
0 = Full Transparent, 255 = full opaque
The other 3 numbers are just 3 RGB numbers to denote the colour to be used. You can change these to get different lightbox colours as below.

The complete source code and sample form can be downloaded from the attachment link below. Enjoy.



It was also suggested that a shape object be used instead with its DrawMode property = 9.
While that would work in some cases, because of the way VFP displays colours, when the form or image control on the form has a Picture set, this is the result - 8 bit colours under the control. Also the control can never support Activex and they come to the top.

posted Monday, September 21, 2009 1:27 PM by bbout | 10 Comments
Filed Under:
Attachment(s): bbGdiLightbox-V6.zip

Beautify your Application Desktop
Been a while since I posted anything.

Came across a desktop image when browsing the other day and saw this application desktop. It looked doable in VFP so I got stuck in and this is the result.

The class is based on the GDI+X classes from the VFPX site and requires VFP9 SP2 or you will not get transparency.

I kept the class simple with few properties to set but that can be easily changed by anyone because the source is included. All the properties are self explanatory.



So just create a form with a nice background and drop as many of these buttons as needed. In my sample I added 4 buttons. Set the above properties as needed. You can resize the buttons but a size of 160 x 160 gives very good results.

Of course place your code in the Click method of each button if you want anything to happen.

 Note that the buttons are transparent and the images partly so. These settings are commented in the code so it is easy to make changes if needed. If you change the size too much the text may appear in the wrong place so open the Class.BeforeDraw method and adjust the following 2 lines to place your text correctly.

lnLeft = this.width/2
lnTop = (This.Height/6) * 5


Here is my form running.



The buttons are interactive. When you mouse over them a Halo appears over the button and it pops up ever so slightly so you know which button you are over. "Diary" in the image below has the mouse over it.


The buttons also react when clicked as shown in this image below, where the top gradient section is flipped when clicked.



Here is another form (attached) with the buttons. The complete source code can be downloaded from the attachment link below.

Have fun.

posted Friday, September 11, 2009 11:34 AM by bbout | 7 Comments
Filed Under:
Attachment(s): bbMediaButtons.zip

GDI+X Pad gets an update with added functionality and tutorial

After some testing and additional functionality programmed in, I have decided to release this new version of the GDI+X Pad - v1.35.

There are a number of enhancements to it, to enable it to be easier to use, which I will list here:

1. The Error handler was changed to the older conventional On Error from the Try...Catch style because Try...Catch was unable to process certain errors and threw up nesting errors. The Error handler now handles improper code statements correctly.

2.The image canvas has some additional functionality.

If you move your mouse over the canvas, a white border appears. If your mouse is at any of the edges, the mouse changes to "sizer" icons and you are now able to grab that edge of the canvas and resize it or move it. Above is an image of the new canvas sized. Also there is some text that shows the current width and height of the canvas, which will assist when designing on your own form.The new size and location are now "sticky" for that code tab.

To see how this works, load the Chess Board snippet and click Refresh to update the canvas.

Now move your mouse over its edges and resize it. The canvas will be automatically refreshed when you release the mouse button after resizing. Note that the new dimensions are displayed above.

3. Below the canvas, is the code editing window. This area too has some additional functionality. in the form of multiple tabs.

You can now have more than one snippet open at a time and work on it. This facilitates the copying and pasting between open windows easily.

You just click the large red "plus" sign to add a new tab. You can have a maximum of 7 tabs open at one time. Now you can load a different snippet into different tabs and switch between tabs easily. Un needed tabs can be closed by moving the mouse over the "x" which highlights to red and clicking.

Clicking this area will close the tab with a warning to save.

4. Because a PRG window was being used to edit code, COPY, PASTE and other editor keyboard shortcuts were not working. This has now been fixed and you have access to Copy, Paste, Cut, Undo, Redo, Select All using the standard keyboard shortcuts.

5. Minor changes were made to the chart screen to make it a bit clearer about its usage.

Since I still have a few enhancements which I want to incorporate, I have not yet released the source. However the updated files can be downloaded from the link below as usual.

The big question is - How is this application useful in helping me design objects using GDI+x?

A short walkthru of a real life example should show the usefulness.

Walkthrough - Creating a gradient button with GDI+X Pad.

1. Start up GDI+X pad and load and run the new Gradient Button sample. 

2. You should see a screen like the one below:

3. Hover the mouse over the canvas edges and resize the canvas so that it resembles the size of a normal button as below. Note the width & height:

We now have our button sized to 146x42 pixels. However the font size is too big for this size button so in the code window go to this line of code (see below) and change the second parameter to 16 to make the font size 16. You could also change the Font name and other properties but for this example, just change the font size from 48 to 16 and refresh (F5)

You will find that the button looks more correct now.

There is one line of code I will explain here:

path3 = This.getpath(this.rectangle,30)

There are no built in functions in GDI+ to get rounded corners for a square or rectangle. In the canvas, I have added a function to give rounded corners, that I have used in other classes. The method is GetPath()

This requires at least 2 parameters (3 optional) and these are :

1. The rectangle to act upon - in out case it is the whole canvas

2. The amount of curvature to apply to the corners as an integer.

3. The third parameter is optional, but you can pass a 0,1 or 2.

  • 0 - All 4 corners are rounded
  • 1 - Only the top 2 corners are rounded
  • 2. Only the bottom 2 corners are rounded.

From the code above and the resultant image you can see that a curvature of 30 is too much for a small button. So change the code to read:

path3 = This.getpath(this.rectangle,15)

and after refresh you get the button now looking like this:

If you prefer you can change the curvature to 5 to get a very subtle change as shown below:

In fact I prefer this curvature of 5.

Similarly the other sections of code can be changed like the colours, font attributes etc. Once you are happy with the result you can create a New snippet and save the code to that snippet. Or you can save the code to a disk file or even copy it to the clipboard.

4. Now in VFP you only need to open a new form and drop the imgCanvas class from the gdiplus.vcx class on the form.

Open the imgCanvas.BeforeDraw method and paste this code you created in the steps above.

Size the imgCanvas object to the dimensions you had for the canvas object (146x42)

5. You will need to add a new method to the form oe imgCancas object if subclassed, called getpath and paste the following code into it:

LPARAMETERS rc,r,nCurvetype

* nCurvetype - 0 full curve, 1 top only, 2 bottom only

* rc = the rectangle

* r = the amount of curve

IF EMPTY(nCurvetype)

    nCurvetype = 0

ENDIF

LOCAL x,y,w,h,xpath,rx

x = rc.X

y = rc.Y

w = rc.Width

h = rc.Height

rx = r

ry=r

DO case

CASE nCurvetype = 1

    * top only

    rx = 1

CASE nCurvetype = 2

    * bottom only

    ry = 1

ENDCASE

WITH _screen.system.Drawing

    xpath = .Drawing2D.GraphicsPath.New()

    xpath.AddArc(x, y, ry, ry, 180, 90) && Upper left corner

    xpath.AddArc(x+w - ry, y, ry, ry, 270, 90) &&Upper right corner

    xpath.AddArc(x+w - rx, y+h - rx, rx, rx, 0, 90) &&Lower right corner

    xpath.AddArc(x, y+h - rx, rx, rx, 90, 90) &&Lower left corner

    xpath.CloseFigure()

ENDWITH

return xpath

Also your pasted code should call this method(form method)

path = ThisForm.GetPath(This.Rectangle,curvature)

or if sub classed and a method added:

path = This.GetPath(This.Rectangle,curvature)

6.  Now if you run your form you will get a similar button. You can change the code like the button text etc. to your satisfaction or better yet just open your snippet in the GDI+X pad, and make the changes there, test and when satisfied, copy and paste it into your own class.


Note: The size and location attributes are not saved with the sample code - yet.

Radek Strouhal reported an error on running the file. I traced this to a corrupt index file. I have updated the zip below. Please test and let me know.

Download the latest update from the link below and don't forget that you need foxtools.fll as well as system.app from this link(now updated).

posted Friday, April 24, 2009 1:47 PM by bbout | 2 Comments
Filed Under:
Attachment(s): bbGDIplusXPadV1.35-05May09B.zip

Update to GDI+X Pad

Just a note to whoever reads this blog and downloaded the GDI+X Pad. that the post has been updated. The download has also been updated to v 1.12.

Please check this link for the update and new download:

http://weblogs.foxite.com/bernardbout/archive/2009/04/14/8096.aspx


posted Thursday, April 16, 2009 2:34 PM by bbout | 0 Comments
Filed Under:

Introducing the GDI+X Pad

Many times when trying out the GDI+X classes I have had to create a form and then type out the code and run the form to see the results. Another problem I have had is looking up sample code to see how things are done. I have always wanted an easier way to manage this.

Note: Post has been updated with some new info. See below. Also the download is now V1.2

The GDI+X Pad is a Visual Foxpro 9 Sp2  application where you can type in your GDI+X code to see how it looks immediately, before actually implementing it in your imgCanvas.BeforeDraw.

Requirements

The GDI+X Pad has a couple of external dependencies.

  • It requires the system.app that comes with the GDI+X classes to be in the same directory as itself. There is a pre compiled file with new functionality uploaded by Cesar and can be downloaded from here http://vfpx.codeplex.com/WorkItem/View.aspx?WorkItemId=20164
  • It requires the foxtools.fll to be in the same directory as well. This file must also be copied from your VFP directory.
  • The code saved, is stored in the snippets table that is included in the download with some sample code already in it.
  • Finally it requires VFP9Sp2 to function properly.

The application is very easy to use and certain elements of the table are easily editable from the front end itself. It is split into 3 sections with buttons and options on the left, the code pane below and the viewing pane above. 

You can run the EXE stand alone or from within the VFP IDE. The only difference is that when run it from within VFP, you get intellisense, which is not available when run standalone. You also get an editing code surface with colour highlighting same as in VFP whichever way you start it.

 The following will describe the different parts to it and the usage.

The main buttons

Reset - Resets your code to the default template. The template is stored in an external file - Default.gdix and may be edited either in the GDI+x Pad and saved or by any text editor to create your own template.

Clipboard - Copies the current code in the editor to the clipboard for pasting into your imgCanvas.BeforeDraw method.

Chart - Displays the GDI+X Colour chart for built in colours. The colours are displayed and their RGB value is shown as you move the mouse over them. You click on a colour to save that RGB colour to the clipboard. You can now paste it into your code as a RGB integer. This form also helps as a reference to the built in colours in GDI+.

Colour - This button opens the typical VFP colour dialog to enable selection of a colour. The selected colour is inserted automatically into your code at the cursor position. To use it, position your cursor where you want the RGB integer to go and click this button. If you select a colour it will be inserted into your code as a RGB integer.

Load - Use this to load code from a file on the hard disk. A sample is provided.

Save - Saves your code to a disk file with a .GDIX extension for later loading.

New - This pops up an Input box where you can enter the name of your snippet. A new record is added to the table. Once you have typed in and tested your code sample, you can use the SAVE button next to it, to save the current code into the table to the current record.

Save - Another save option. This one saves the current code in the edit window to the current record in the table.

The Snippet list

Below the buttons above, is the list of saved code snippets. I have included some samples for easy reference here. Any new snippets you save will be listed here. Double click a snippet to load its code into the editing pane. If you need to make changes these can be saved back into that record.

Snippet Description

The description of each snippet is displayed here. Note that you can edit this and the changes are saved immediately.

Finally on the bottom left are two more buttons

More Buttons

Delete

This will delete the current record from the snippet table

Refresh (F5)

This is used to run the code in the code pane. If you have loaded code from disk or from the snippet list, you can run the code to test it out immediately by pressing F5 or clicking this button. The result, if there are no errors will be displayed in the Viewer pane above.

To the top right is the viewing pane and this deserves no further explanation. It is here that what you have coded will be displayed, when you hit Refresh or F5.

The Code Window

Finally you have the code window. Here is where you will type in or edit your code before running. A default template is always accessible using the Reset button to start with a clean state.

This is just like the VFP code window with syntax colouring and scroll bars. In addition if you run the exe within VFP you also get Intellisense. At this time I have been unable to get proper usable intellisense at runtime in this window.

A simple walkthrough

1. Click the Reset button to reset to the default

2. Highlight the part of code that says 100,100,100

3. Click the "Colour " button and select any colour. Click Ok to close the colour dialog.

4. Your selected colour, converted to a RGB integer is inserted into your code, with a number replacing the highlighted 100,100,100.

5. Hit F5 and the viewer pane will be filled with that colour.

6. After the above line add these 2 lines:

loBrush = .Solidbrush.New(color.orange)

logfx.FillEllipse(loBrush,30,30,300,200)

7. Hit F5 and an ellipse will be drawn on the screen.

8. You can now use the upper Save button to save this to a file on disk or create a New snippet and use the lower Save to save this code into the snippet table.

Additional Info

1. The application has built in error trapping even for the code you enter in the code window. The following screens will show that, where I deliberately enter a wrong line into the code window and hit F5 to run this.

The error trapping kicks in and even though this is runtime, you are prompted as to the source line that caused this error, which can now be corrected.

2. The thick green line between the viewer pane and the code pane is a splitter bar that allows resizing the two panes to whatever sizes you like. Just grab it and drag up or down to size.

3. The form may not be resized but may be maximised or minimised.

Finally here is another image with a code segment of mine copied out of the glowing buttons class.

I am not releasing the source as yet, only the relevant exe and dependant files. I will release the source once this project has been completed fully .

All suggestions and bugs/fixes may please be posted here on this blog or on www.foxite.com and mention GDI+X Pad. Enjoy

So download the file below, get the correct system.app and foxtools.fll and give it a go. You may actually have fun programming in GDI+.

Update 16 Apr 2009

Thanks to Koen for pointing out that the Colour Chart did not work as "advertised"

This was because despite the images being compiled into the exe, the functions I was using expected them to be on disk. I have changed the functions and the chart form works properly now. 

You move the mouse over the colours and the top box shows the colour under the arrow. If you click, the selected colour and RGB is displayed in the bottom box and also copied to the clipboard. You can now Ctrl+v to paste the RGB integer into your code.

Please download the updated version from the link below.


posted Tuesday, April 14, 2009 5:18 PM by bbout | 7 Comments
Filed Under:
Attachment(s): GDIPlusxPad112.zip

Creating the VFP Base Classes with GDI+x - The 3D Option Buttons

Following on from my previous post about creating check boxes completely with GDI+x I decided to try something a bit different and create a 3D Option Button set with colour schemes. What follows is about this class as well as how to set it up and also to create your own colour schemes, in addition to the ten schemes included.

Important:
The GDI+X classes that are used in this class use Functions in system.app that are fixed and you will get errors if you use the release version. As pointed out by Cesar, the latest update with bugs fixed has been posted on the CODEPLEX/VFPX site.

Please download the updated SYSTEM.APP from this link as provided by Cesar:

http://vfpx.codeplex.com/WorkItem/View.aspx?WorkItemId=20164


Before you begin, you should know that this class uses the GDI+x classes found at the codeplex site which you need to download. Also to use the ColourSelector tool to create your own schemes, you must include the system.app from the GDI+x classes in the same directory as the tool.

Also you need VFP9Sp2 since this class uses Transparency.

You must also resolve the location of GDIPLUS.VCX in my class, to where you have extracted it.

Before we begin, here is a sample of the class with all the colour schemes.



To use the class is simplicity itself so follow along.
Open a new form and drop the class onto the form. Resize it but note that the class also resizes itself at runtime to accommodate the number of option buttons defined.

The image below shows you the only properties you need to set.



Value - this tells the class which button is to be shown as selected.
ButtonCount - the number of buttons to be drawn
ButtonSize - In pixels the size of the button. Don't make them too small as then detail may be lost. The size entered here determines the final height of the class as well as the size of the font used.
Captions - Comma delimited string of the captions.
ColourScheme - Enter the string here exactly as per the description of the property.
Enabled - .T. or .F. This can also be changed at runtime.

These are the only properties that need to be set. The class has a Value property that will show which button was selected by the user.

Unfortunately I have not added the option of showing what the class will look at design time, but that may come later with a builder.

Here is another sample of the different schemes including the Enabled = .F. at the top right.




Creating your own schemes
Creating your own schemes is not that difficult provided you follow exactly this tutorial on how to do it. You can either replace a scheme with one of your own or add an additional one or two or more.

First, if you want to add an additional scheme, these are the steps, as you will need to edit the class.

1. Open the class for editing and open the method SetupColourSchemes.
Change the number of schemes and add your own.
DIMENSION This.colourschemes[10]
With This
    .colourschemes[1] = "Brown"
    .colourschemes[2] = "Blue"
    .colourschemes[3] = "Purple"
    .colourschemes[4] = "Green"
    .colourschemes[5] = "Gold"
    .colourschemesDevil [6] = "Aqua"
    .colourschemes[7] = "Steel"
    .colourschemesMusic [8] = "Violet"
    .colourschemes[9] = "Brick"
    .colourschemes[10] = "Crimson"


So if you wanted to add a scheme say Myscheme you would need to re-dimension the array
   
DIMENSION This.colourschemes[11]
and add the scheme after Crimson
.colourschemes[11] = "Myscheme"

Next you need to add a property to the class called colourscheme11 to store the colours for this new scheme.

There are 18 different colours used in the class and these need to be assigned to this property as the return value of a RGB colour. This is the number you'd get if you typed at the command prompt:

?RGB(234,222,128) which would give you 8445674

The 18 colours need to be entered into this property as a comma delimited list of numbers as the schemes 1 to 10 have already been done by me. While this may seem difficult, just read on and see how easy I have made it to do.

The following image shows where the colours are used, their order and sequence. This sequence must be strictly followed from 1 to 18.

Colour Scheme Key




The easiest way is to first get the colours you will use as an image. You can download and use the image below and change the Hue & Saturation to get different shades in any paint program. Click on it first to get the proper resolution and then save it.



Once saved change the Hue/Saturation to get your desired colour scheme and then save with a new name as a BMP.


The same image with a Hue = +30 and Saturation = +130 applied is shown at the very end.


Included in the download is an EXE - colourselector.exe. This needs system.app in the same directory. Just run it and click the button to load the image you just saved.

Select your new colourscheme11 property and click the magnifying glass icon to open the property in an edit box as shown below.


Now referring to the image of the Colour Scheme Key from above to get the sequence and location, move your mouse over the area of the image in the colourselector and click to select your colour. Once you are satisfied it is the correct colour, click inside the Properties editbox and (Ctrl+v) paste the colour number. Do this in sequence for each of the 18 colours, separating them with commas. When you are done save the class. Make sure there is no comma after the last number.

Now to use that scheme just change the property colourscheme of my class to the name of your new scheme. In the example above it will be Myscheme.

Nothing could be simpler.

If you have any problems please let me know as well as any comments or improvements and any additional properties. I'll see what I can do.

Enjoy


Class has been updated to V1.02

Fixes:

1. Removed redundant code from Sample forms

2. Updated class so clicking on caption also fires.

3. Moved checking code out of BeforeDraw to avoid flicker

2&3 were made on suggestions by Yousfi. Thank Yousfi.


posted Saturday, March 28, 2009 4:23 PM by bbout | 2 Comments
Filed Under:
Attachment(s): bboptionclassv1.02.zip

Creating the VFP Base Classes with GDI+x - The Checkbox

A reader on my blog posted - why don't I create other base controls with GDI+x so I thought I'd give it a shot. This post is about recreating the VFP Base classes using pure GDI+ and the GDI+x classes to achieve neat looking base classes.

When I say "Base Class" I mean with VFP intrinsic ability to bind fields to controls. So while not all PEM's available in the Checkbox have been implemented the two most important have been - DataBinding using the ControlSource and of course sprucing up the UI experience.

After a day and a half, this is what I have come up with. This classes can be improved in a number of ways, including improving the UI but that will have to be in later versions.

Please note that to get Translucency you need VFP9Sp2.

Here is a form (included in the download) that displays some of the PEM's of the new control and also allows you to play a bit with the properties.

I have added most changeable properties to the Favourites tab for easy access. This class has the following properties that can be set. Note that some are dependant on others.

1. Background - Solid, Gradient or None.
2. Border or no border.
3. Colour of Background (colours for gradient)
4. Caption
5. 4 background shapes - Rectangular, curver top and bottom and all rounded corners
6. Ability to change the font, colour and actual displayed icon in the check box (tick, circle etc)
7. Square or circular checkbox.
8. Size of the check box
9. Ability to vary the direction of the gradient.
10. Transparent background and ability to vary the Alpha channel.
11.Vary the amount of curvature of the background.
12. Ability to change the colour and font of the caption.
13. Visual feedback when the control has the mouse over
14. As mentioned earlier, this control can be bound to your data the same as the original VFP checkbox control. So it will read and display the bound value as well as set the value in the table for the bound field.

As you can see above, by comparing my control to VFP's native, it does make a big difference to your UI

To make it even easier to use I have also included a builder that will allow you to change most custom properties easily.

To use this class, just drop it on a form the usual way and resize it to what you require.

In the properties window, select the Favourites tab and select the item - aaCheckboxBuilder. When you do, a button will appear above as in the picture. Click this button to open the builder.

The builder is very easy to use and most properties will update live so you can preview them. I have made some notes about some settings as marked in the image below which require some additional comment.

1. This item is what is displayed in the check box. The character above is the tick in the Wingdings font. The easiest is to open the Character Map from the system tools and preview the characters available. Once selected this can be copied to the clipboard and pasted here. Make sure you add the correct font.(2)

3. If no gradient is selected the control will use the colour on the left. There are 4 modes of gradient and by switching your colours you will get 4 more..

Another point I need to make that is important. With a number of these controls on the form you will notice that the form first appears, then the class with an X in the middle then the controls draw the image. This is a problem with the GDI+x. specifically the imgCanvas class, but can easily be fixed. Here's how.

Open the imgCanvas class in VFP and open the INIT method. Scroll down and after the last line in the method add this:

This.Draw()

Close and save the class. What this will do is that it will draw your controls before the Form.Show. The effect will be a slight delay in the form appearing, but that is much better than having the empty controls with the X.

Please let me know of any problem or errors in the code. Also I am welcome to suggestions for improving this class both in functionality as well as in UI appearance, with the emphasis on the latter.

Enjoy

Update:

Following feedback received, the class has now been updated to v1.1 With:

1. Disabled textboxes in builder now enabled.

2. Enabled property added to Favourites so the control can now be Enabled/Disabled at runtime.

Future improvements...?

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

posted Thursday, March 26, 2009 3:06 PM by bbout | 4 Comments
Filed Under:
Attachment(s): bbCheckboxClassV1.1.zip

White Butttons are not that bad looking after all

Been working off and on, on a set of, believe it or not, White buttons using GDI+x  So far they have come out pretty good looking. May complete them one day and post them.

What do you 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

posted Friday, March 06, 2009 1:06 PM by bbout | 4 Comments
Filed Under:

Decorating a Grid with GDI+
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

posted Tuesday, March 03, 2009 1:14 PM by bbout | 1 Comments
Filed Under:
Attachment(s): GridThemeImages.zip

VFP Shape Tips & Techniques

Here are a couple of tips for getting things done with your classes using the Shape control.

With a listbox control, you have to actually click on it before any row is selected. If, for any reason you wanted to be able to just move your mouse over it and have a row selected, you will find that you cannot achieve this with the plain control. That is because this behaviour is not native.

But given that you may want this specific effect, and remember that this technique can be used for other controls and your custom classes as well, here we go:

After you have setup your Listbox to how you want it, from the toolbar select and drop a shape on the form and size it to fit exactly around your list, excluding the scrollbars. You could do this programatically, using sysmetric, but I leave that to you. The red box indicates the size and position of the shape on your listbox.

Also drop a simple label control below the listbox to show the result. Set its :

AutoSize = .T.

BackStyle = 0

Set the following properties of the Shape:

BackStyle = 0 - Transparent

BorderStyle = 0 - Transparent

Double click the shape and add this code in the MouseMove method:

*Shape::MouseMove

LPARAMETERS nButton, nShift, nXCoord, nYCoord

This.Visible = .F.

MOUSE CLICK

* Leave out this next line at your peril!!

DOEVENTS

This.Visible = .T.

* update the label with the item selected.

ThisForm.Label2.Caption = ThisForm.List1.Value

 

 

 

That's all. Run the form and as you move the mouse over the listbox, the highlight also moves and the label shows that the value is being changed.

 

Often I design a button or some other control on a form that will involve a number of other controls. When I am satisfied with the result, I select all the controls involved and save them as a Class for later use. This puts all the controls into a container and I can easily add the relevant PEM's to the class to complete it.

 

For instance to achieve this button I used an image control on top of which I dropped a Label control. When the mouse moves over the "button" I want the highlight to change. For this I just hook into the MouseEnter and MouseLeave events and change the image there. However when I add a label on top of the image control, things change.

 

 

What I have noticed is that most dev's just add code to the Label MouseEnter/MouseLeave events to call the image MouseEnter/MouseLeave which does the actual switching of the images. At first this may seem ok, but on closer examination you can see that something else is taking place that will cause the "button" control to flash and flicker.

 

This image shows the problem.

 

The MouseEnter of the image first fires and the code is run to change the image. If you now move off the image it changes back. So far so good.

 

However if you now move the cursor over the label, the events that occur are :

 

1. The MouseLeave of the image fires - image is changed

2. The MouseEnter of the label fires which fires the MouseEnter of the image which changes the image again.

 

The same sequence occurs when the mouse is moved off the label but in reverse. This flipping of the image twice causes the flicker.

 

I received an email once about my "GlassButtons", where the DEV had added a Label control over it and did as I did above. His complaint was that the flicker was terrible. The shape came to his rescue.

 

It is very easy to solve this. Just drop a shape control or if you want the control to get focus (tab order) use an invisible button.

 

In my image the shape is shown with the green border, but you will hide it by making the BorderStyle = 0. Also it will need to be sized either at design time or at runtime (friom the init) so that it completely covers the image and label controls.

 

Now all that is needed is to move all code to flip the images into this shape control's MouseEnter and MouseMove. No code is needed in either the image or label controls. You can hook the click to the parent container click.

 

Now moving the mouse over the control will only fire the MouseEnter once and when you move off, the MouseLeave once.

 

Goodbye flicker.

 

More tips & tricks soon.

 

Note that there is no download since there are only a few lines of code and the technique is the main thing.

 

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

posted Tuesday, March 03, 2009 9:18 AM by bbout | (Comments Off)

Don't let VFP's CLEAR ALL command scare you

When developing, how many times have you had to issue a CLEAR ALL in the command window only to find your objects and other settings also were cleared?

For me I use Foxtabs, as well as some additional tools accessed by custom toolbars. All these are loaded at startup by my custom VFPSTART.PRG and issuing a CLEAR ALL wipes all these utilities out and I have to run VFPStart again.

In fact, in the latest issue of FOXROCKX Ric Schummer, in his article on FoxTabs has this to say:

The reason I made  the  request(for the -m option)  is executing CLEAR ALL  in  the Command Window will wipe out  the  instance of FoxTabs. I want something on the Tools menu so I can quickly get my tabs back after testing a program or needing to reset the development environment.

Now those of you who have never heard of Burkhard Stiller and have never visited his Blog, are missing out on some very interesting and revealing ideas and posts. This blog post  is my implementation of an idea he posted here that I find excellent. I am talking about "Unbreakable Objects". Since Bukhard has done such an excellent job, I will not repeat what he has explained so well. Just go to the link above, and read and digest all 3 parts of his post on Unbreakable Objects and this will give you a better insight into what I am going to show here.

OK. With all that cleared up and armed with your new knowledge of VFP's _shell let me show you what I have done to implement this idea in my IDE.

As Bukhard explained stuffing a VFP command into the system variable _shell causes VFP to execute that command immediately.

Now I use a VFPSTART.PRG to load all my utilities into the VFP IDE on startup and so should you. Basically for those who do not know, you can get VFP to run any PRG or APP on startup by a setting as shown below.

Now here is the partial contents of my VFPSTART.PRG

* both vfpstart & bbPersistvars prgs must be in the same directory, usually VFP

cPrg = Justpath(Sys(16))+"\bbPersistvars.prg"

* create the variable

IF Vartype(_screen.oMyVars) = "U"

    _screen.NewObject("oMyVars","bbVars",cPrg)

ENDIF

* fill the shell cmd

_Shell = [do ]+ cPrg +[ WITH 'Do ]+SYS(16)+[']

* add a menu item to Tools

m.nBar = 0

For m.i = 1 To Cntbar("_MTOOLS")

    If Prmbar("_MTOOLS", Getbar("_MTOOLS", m.i)) == Strtran ("\<PersistVars", '\<', '')

        m.nBar = Getbar("_MTOOLS", m.i)

        Exit

    Endif

Endfor

If m.nBar == 0

    m.nBar = Cntbar("_MTOOLS") + 1

Endif

Define Bar m.nBar Of _mtools After _mtl_references ;

PROMPT "\<PersistVars" ;

MESSAGE "Persists your IDE"

* set the mark on

Set Mark Of Bar m.nBar Of _mtools To .T.

* save bar for later

_screen.oMyVars.nBarnum = m.nBar

* Function ShowPersistMenu is at the end

On Selection Bar m.nBar Of _mtools Do ShowPersistMenu

* Below you can add all the other commands you normally have in VFP start

* I have left some of mine in as an example

Do c:\vfp8\tools\versatools\versatls.App

Define Bar 6 Of POPUTIL Prompt "Messagebox Wizard" ;

MESSAGE 'A Messagebox Wizard'

On Selection Bar 6 Of POPUTIL Do c:\vfp8\tools\msgbox\mboxwiz.App

Define Bar 15 Of POPUTIL Prompt "Intellisense" ;

MESSAGE 'Add to Intellisense'

On Selection Bar 15 Of POPUTIL Do c:\vfp8\is_customizer.prg

Define Bar 16 Of POPUTIL Prompt "Form Runner" ;

MESSAGE 'Run/Edit forms'

On Selection Bar 16 Of POPUTIL Do Form c:\vfp9\mytools\formrunner.scx

Define Bar 18 Of POPUTIL Prompt "SQL Select" ;

MESSAGE 'Connect to Local SQL'

On Selection Bar 18 Of POPUTIL Do Form c:\vfp9\sqlselect

With _Screen

If Vartype(.oMyVars)= "O"

With .oMyVars

.AddProperty("oQuickFormat")

.oQuickFormat = Newobject('formatbuttons','c:\vfp9\formattoolbar')

.oQuickFormat.Show

Endwith

Else

.AddProperty("oQuickFormat")

.oQuickFormat = Newobject('formatbuttons','c:\vfp9\formattoolbar')

.oQuickFormat.Show

Endif

Endwith

Do c:\vfp9\Getobj.prg

Set Procedure To c:\vfp9\bbUtility.prg Additive

* add menu item to tools

Do c:\vfp9\tools\foxtabs\foxtabs\foxtabs.App With "-M"

* actually run it

Do c:\vfp9\tools\foxtabs\foxtabs\foxtabs.App

* This is run when the menu option is ticked/unticked

Procedure ShowPersistMenu

LPARAMETERS tnBarnum

If Vartype(_Screen.oMyVars) = "O"

_Screen.oMyVars.Persistvars = Not _Screen.oMyVars.Persistvars

Set Mark Of Bar _screen.oMyVars.nBarnum Of _mtools To _Screen.oMyVars.Persistvars

Endif

Endproc

Now certainly your PRG will differ. Most are custom settings & utilities I load into my IDE, but the items relevant to this post I will explain here:

 cPrg = Justpath(Sys(16))+"\bbPersistvars.prg"

bbPersistvars is a custom class which I will explain about soon. This class must be stored in the same directory as VFPstart. The above line just establishes the full path & file name of my custom class.

Next we create a new object in  _screen. It is this object and its properties we will make unbreakable to Clear ALL

 IF Vartype(_screen.oMyVars) = "U"

    _screen.NewObject("oMyVars","bbVars",cPrg)

ENDIF

bbVars is a class that is in the bbPersistvars.prg

* fill the shell cmd

_Shell = [do ]+ cPrg +[ WITH 'Do ]+SYS(16)+[']

This is the killer line of code. What we do is stuff _shell with this command (in my case)

_shell = "do c:\vfp9\bbPersistvars.prg with c:\vfp9\vfpstart.prg"

So what happens is that VFP will now try to run the command stuffed into its _shell and so bbPersistvars is run with a parameter of the VFPSTART.prg - more later.

The rest of the code is bog standard vfpstart stuff, except here I save the menu item into my persistant object for later use:

_screen.oMyVars.nBarnum = m.nBar

Basically I add a menu item to Tools so when unchecked, CLEAR ALL wil not persist my object.

The final piece of VFPSTART I want to explain is the function that gets run when the menu item is ticked/unticked:

The code is simple enough. Basically I store the value of the Ticked/unticked in my custom persistant object.

Now here is the contents of my bbPersistvars.prg which I will explain inline.

 * This is called from the _shell statement

LPARAMETERS tcShellcmd

* If we have an object then set it up

IF Vartype(_screen.oMyVars) = "O"

    _screen.oMyVars.fillit(tcShellcmd)

ENDIF

Here I call the fillit function passing it the full path and filename of vfpstart

* This class is used in vfpstart - like this

    * IF Vartype(_screen.oMyVars) = "U"

* _screen.NewObject("oMyVars","bbVars",cPrg)

* ENDIF

Here the class is defined

DEFINE CLASS bbVars as session

persistvars = .T.

nBarNum = 0

* a default value - changed later

cShellcmd = "DO c:\vfp9\bbpersistvars"

HIDDEN cShellcmd

HIDDEN baseclass, class, classlibrary, comment, datasession, datasessionid, name, parent, parentclass, tag

HIDDEN destroy, error, init, readexpression, readmethod ,resettodefault, writeexpression

FUNCTION fillit

    LPARAMETERS tcShellcmd

    IF VARTYPE(tcShellcmd) = "C" AND NOT EMPTY(tcShellcmd)

        This.cShellcmd = tcShellcmd

    ENDIF

ENDFUNC

Here again we have the killer method. When the class is destroyed by issuing a CLEARALL we re-stuff VFPSTART.PRG into _shell which starts the cycle all over, thus persisting the apps & tools loaded into the IDE.

FUNCTION DESTROY

* reinsert instantiation

    IF This.persistvars

        _shell = This.cShellcmd

    ENDIF

ENDFUNC

* just for fun

FUNCTION MyDoCmd(cCmd2Run as String) as Boolean helpstring "Runs the command passed"

    TRY

        &cCmd2Run

    Catch To oEx

        ?oEx.Message

    ENDTRY

ENDFUNC

FUNCTION ERROR

ENDFUNC

ENDDEFINE

And that is all that needs to be done. Of course you can make this as complex or as simple as you want. You have an object that is "persisted" in VFP till you tell it not to. So using this you can store settings and also read them in from disk.

You can save your memory vars to disk in the DESTROY and load them into the object so they are available even if a CLEAR ALL is issued.

You will find a copy of my VFPSTART.PRG and bbPersistVars.PRG. You will need to adapt it to your own tastes.

Once you get the basic idea about how powerful this technique is, then the juices will flow and more ideas of your own will come flowing.

So if you now issue a CLEAR ALL, vfpstart will be loaded automatically and all your tools will be restored. You can even save and restore your memory variables if that is what you need.

Enjoy.

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

posted Thursday, February 26, 2009 11:24 AM by bbout | 3 Comments
Attachment(s): bbPersistVars.zip

Transparent Forms with VFP Revisited with GDI+x

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

posted Friday, November 07, 2008 3:14 PM by bbout | 3 Comments
Filed Under:
Attachment(s): bbTransformBlur.zip

Glow-In-The-Dark Buttons with GDI+X

The GDI+x Samples have a form that displays a "Halo" for text. So taking that idea I adapted it for these glowing buttons.

To use these buttons you will need the GDI+x classes on the VFPX site.

http://www.codeplex.com/Wiki/View.aspx?ProjectName=VFPX&title=GDIPlusX

Click on the link on this page that says Latest Release of GDIPlusX and download the latest stable release. Do not download the Beta as that is not complete and may not work properly.

I havd also posted a tutorial on how to use my classes including the supplied builder. You can find the post here. Most of the points are relevant here too.

Ok. Using these buttons is just a matter of dropping them on a form, sizing them to the required size and then running the builder provided in the Favourites tab. You may have to delete the image stored in the Picture property of the sample form as these images are not included. However the builder will show what exactly the button will look like at runtime and also generate a new image.

All the properties you need to change are in the Favourites tab except for the Enabled property.This can be set at design or runtime as I have hooked into the Enabled_Assign. The colours assigned can be tested for the best mix of Font and Glow and you get immediate feedback in the builder.

Here are some samples I created earlier. The form is included.

Note what the Disabled button looks like.

And here is the above form where the button "glows" when the mouse passes over it (2nd down on the left in case you miss it)

The button also gives feedback when Clicked where the border becomes black.

Lastly some interesting toolbar buttons are possible using the Wingdings and similar fonts, resizing the button and a judicious use of colours.

Finally if you create a great big button as big as your screen, switch off the lights at night and pass the mouse over it, you will actually see that the button does "glow in the dark" :)

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

posted Friday, October 24, 2008 12:09 PM by bbout | 5 Comments
Filed Under:
Attachment(s): bbGlowingButtonV1.zip

More Posts Next page »
Powered by Community Server, by Telligent Systems