True Multithreading in VFP
In this 4th part I will describe here a way of
obtaining true multi threading with VFP and the Interop Toolkit Usercontrol. As
you know this is impossible in VFP alone although there are some ways of
achieving this through COM and use of timers.
The method for doing this has been adapted from the code found here:
http://www.codeproject.com/KB/vb-interop/VB6InteropToolkit2.aspx
You should also read this article thoroughly.
So fire up VB 2005 Express and create a new
Interop User Control project..See here for how. Name it MultiThreadedControl. Rename the
InteropUserControl.vb to bbInteropUserControl.vb
Open the control in design mode and add the following 3
objects to the user control:
Label -> change the Name property to LabelMessage
Progressbar
Backgroundwoker (found under components)
Arrange them so the control looks like this:
Now double click the control to open the code
window, and type in the following code as shown or copy and paste the code in
green below.
'Please enter any new
code here, below the Interop code
Public Event StartEvent(ByVal StartEventText As String)
Public Event FinishAsyncEvent(ByVal EndEventText As String)
Public Sub StartProcessing()
Try
' commented out see explanation later on
'RaiseEvent
StartEvent("Starting .NET process ...")
Me.BackgroundWorker1.RunWorkerAsync()
Catch
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object,
_
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles BackgroundWorker1.DoWork
'wait for a while
Static prog As Integer = 0
' moved from SUB above. See explanation below.
RaiseEvent
StartEvent("Starting .NET process ...") While (prog < 100)
System.Threading.Thread.Sleep(250)
prog = prog
+ 2
Me.BackgroundWorker1.ReportProgress(prog)
End While
prog = 0
End Sub
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender
As System.Object, _
ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
Handles BackgroundWorker1.ProgressChanged
Me.LabelMessage.ForeColor =
Color.Red
Me.LabelMessage.Text = "Working
in background..."
Me.LabelMessage.Visible = True
Me.ProgressBar1.Value =
e.ProgressPercentage
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal
sender As System.Object, _
ByVal e As
System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles BackgroundWorker1.RunWorkerCompleted
Me.LabelMessage.Visible = False
RaiseEvent
FinishAsyncEvent("Background Interop User Control process finished.")
End Sub
Private Sub BackgroundWorker_Load(ByVal sender As
System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Me.ProgressBar1.Value = 0
Me.LabelMessage.Visible = False
End Sub
End Class
Correct any errors in your typing.
Make sure the backgroundworker has had the appropriate events set:
Also make sure that you turn on progress
checking as shown below:

That's it for the net part. Now build your
solution and an ActivexDll will be created called MultiThreadedControl.DLL and
will appear as an activex in VFP.
Switch over to VFP now and create a new form. Add objects and set their
properties as shown:
Edit2 is an editbox that is made ReadOnly and
the disabled BaclColor set to yellow.
Our Usercontrol is added at the bottom in the usual way an activex is added.
Now lets get on with the VFP side code.
In the button.click event add code as shown to first clear the editbox out,
then display a message and finally to kick off the background process. As you
type you can see Intellisense takes over and displays the Sub we exposed in
.Net
Public Sub StartProcessing()
Now you need to hook in the 2 events we exposed:
Public Event StartEvent(ByVal StartEventText As
String)
Public Event FinishAsyncEvent(ByVal EndEventText As String)
So doubleclick on the Interop control and select the StartEvent from the list.
You can see that VFP adds the appropriate parameter statement. Add code as
shown to broadcast the start event.
Funnily enough I was unable to get this event to
fire although the code to start the process does work.
Later on - Correction
It appears that you cannot raise an event within an exposed Method in a .NET COM if you call that method directly. You can only Raise the event if the trigger is within .Net.
In the code above :
Public Sub StartProcessing()
Try
RaiseEvent
StartEvent("Starting .NET process ...")
Me.BackgroundWorker1.RunWorkerAsync()
Catch
End Try
End Sub
I am calling the exposed SUB StartProcessing from my button and this in turn is Raising the StartEvent. This does not work in VFP and .NET.
So move the Event into the method that actually does the work. That is triggered within .NET and you can raise the event there.
RaiseEvent
StartEvent("Starting .NET process ...")
While (prog < 100)
System.Threading.Thread.Sleep(250)
prog = prog
+ 2
Me.BackgroundWorker1.ReportProgress(prog)
End While
Why this happens is anyone's guess but happen it does. Go figure.
![]()
Also add code to handle the FinishAsyncEvent as shown:
Before we finish, make sure the form has these
properties set:
Your form is ready to run. So just go ahead and
run the form. Type something in the Topmost editbox. Then click the process
button to kick off the background process in another thread.

You will find that you can continue typing in
the Editbox and do other things, while the process runs. Feedback on its
progress can be seen by the progress bar. Once the process has completed, you
are notified by the FinishAsyncEvent firing. This causes our final piece
of code to run and displays the message in the yellow editbox.

And there you have it. True Multithreading in
VFP with .Net. But why stop there. How about adding another MultiThreading
component. Below is an image of a form - multi2.scx, running 2 processes while
allowing you to type and do other processes.
In the next article I hope to show how you can spawn
multiple processes in separate threads using COM and a .Net MultiThreadFactory
object.
The complete source code for the above can be downloaded from the attachment link below:
Adding reflections to the bbZoombar class.
Over the holidays, I have done some additional enhancements to the bbZoombar class. Wouldn’t it be nice to have the icons reflected on the bar, with the reflections moving and zooming as well? Well this class now has them.
Also the class has been revamped to allow for more than 9 buttons. Now you can have up to 99 but that would be overkill.

I have also added a builder to the class. To use the new class, just drop it on a form, resize the container and arrange the grey bar centrally with the proper height and top. (see note below)
Next add code to the init as before:
* sample calling code
WITH This as zoomcontainer
.addbuttons("FirstButton","explorer96.png","This is the first button")
.addbuttons("SecondButton","folder96.png", "Click here for a file")
.addbuttons("ThirdButton","monitor96.png", "Monitor events")
.addbuttons("FourthButton","music96.png","Play your music")
.addbuttons("FifthButton","photo96.png","View your photos")
.addbuttons("SearchButton","search96.png","Search for anything")
ENDWITH
* this must be called
DODEFAULT()
The above code will give me 6 buttons. The parameters are as before:
P1 = Name of the button stored in the TAG property for identifying the button
P2 = The name of the icon to use. PNG’s are best since they resize properly and can also have a transparent background
P3 = This is the tooltip text for the button. You will have to switch ShowTips on in your form.
As you can see I have added more properties for more control. These properties can be set individually or using the new _memberdata builder included in the class.
The new properties to be set are:
ShowReflections – Reflections on or off
CenterZoom – Zoom centrally or zoom upwards
ReflectionEXT – the extension for the reflections
ButtonSize – The initial size of the buttons.
This last was added since PNG images look good with the main icons but flicker when used in the reflections. For reflections, GIF is the best format and the one I use. BMP’s do not look good when shrunk.
All the above properties have been brought together in a builder using the property name:
A_Builderx

The builder is stored in the class as a form – propertywizard.
If you highlight this property in your Favourites, and click on the button to the right of the property, the builder will open where you can make all the above settings. All properties have tooltips and are self explanatory.

Once you have applied the settings in the builder, just run the form and enjoy the effect.
To trap clicks, just add code in the ButtonClicked method of the class. The whole button object is passed, so you can actually use any property. However the name passed as the first parameter above is stored in the TAG so you could have code here like this:
LPARAMETERS toButton
LOCAL cTag as String
cTag = toButton.Tag
DO CASE
CASE cTag = "FirstButton"
* do something
CASE cTag = "SecondButton"
* do something
CASE cTag = "ThirdButton"
* do something
* etc
ENDCASE
Included in the zip is a form – inatoolbar.scx where the class has been added to a toolbar class, that behaves just like any other toolbar.
Note: The initial TOP of the buttons will depend on the position of the grey bar. The initial TOP will be set so that about 1/2 of the button protrudes above the grey bar. So you will also need to resize and reposition the grey bar so that the buttons appear properly.

As always I welcome your comments and suggestions.
You can download the complete source and this document from the link below:
http://www.foxite.com/downloads/default.aspx?id=178
Hope you all have a great New Year 2008.
The Zoombar Class
From the first time I saw this class here
http://www.devcomponents.com/dotnetbar/BubbleBar.html
I liked it a lot. Only problem was it was in .NET and not VFP and I did not want all that overhead.
Emerson Reed did a good class here http://weblogs.foxite.com/emersonreed but it only had 2 states so was more of a popup button class rather than a zoom class.
So I decided to develop this from the ground up to suit my needs and with an actual zooming effect. The class I came up with was easier to program than I first thought.

The Class
The class library consists of 2 classes:
1. A zooming button class that can be used by itself and
2. A container class that holds a series of buttons that would zoom when the mouse was moved over them.
The buttons had to be able to be zoomed from the bottom up (bottom fixed) as well as to zoom from a central point. Also the container had to be able to move the remaining buttons around the zoomed button.
Another need was that the buttons were centrally arranged in the container whether odd or even numbers of buttons were used.
The class was to be self contained as well as have a handler for the click. Of what use is a button that does nothing when you click it?
The Zoom Button Class - Zoomimage
The whole animation of zooming takes place in the MouseMove of the button. This is a VFP image class.
So if the mouse is moving over the button from Left to Right, the button should zoom till the central point is reached and then as the mouse moves away from the centre, the button un zooms and vice versa for the opposite diretion. So find this central point, zoom till reached and then unzoom. There is also the fact that the direction the mouse is moving in, should also be stored and known else if you moved the mouse from right to left, the button would first shrink till the central point and that was undesirable.
All the original positions of the button are stored for later use here:
WITH This as image
.oldwidth = .Width
.oldheight = .Height
.oldleft = .Left
.oldtop = .Top
.vcenter = .OldLeft+INT(.Oldwidth/2)
.hCenter =.oldtop+INT(.oldheight/2)
.oldbottom = .top+.height
ENDWITH
Also the button acts differently when placed on a form or in a container. So this code was put in the Zoomimage.MouseMove:
LPARAMETERS nButton, nShift, nXCoord, nYCoord
*is this in a container or form
IF This.Parent.BaseClass = "Form"
This.zoomimage(nXCoord)
ELSE
bb = This.zoomimage(nXCoord - this.parent.left)
ENDIF
This.Parent.Reposition(This)
Zoomimage.Zoomimage
All the zooming happens here in this method. The position of the mouse cursor is passed into this depending on if it is a form or container that is the parent
If cStr = "LEFT"
inc = Int(((nxcoord-.oldleft)*10)/(.oldwidth/2))+1
Else
inc = Int(((.oldleft +.oldwidth - nxcoord )*10)/(.oldwidth/2))+1
Endif
The 10 here means that the zooming is done in 10 steps depending on the original size of the button.
.zoomfactor is the amount of zoom we want. A larger number means a greater zoom.
The next bit of code zooms the button as needed depending on whether it is a “bubble” zoom of centre zoom:
If Not .centerzoom
.Height = .oldheight + inc
.Top = .oldbottom - (.Height)
Else
.Height = .oldheight + inc
.Top = .hcenter - (.Height/2)
Endif
Finally I store the mouse position so that we can check next time to find the direction of movement: This.oldnx = nxcoord
And that is all that is needed. The class can be used on its own as below:
The ZoomContainer Class

This is used as a button bar and is responsible for creating the buttons, repositioning them and maintaining that position and has the button click handler.
ZoomContainer.Init
I have added some sample code to show how the buttons are added. Important is the DODEFAULT() since this is what initially positions the buttons and sets up the anchor of the container depending on its centerzoom property.
ZoomContainer.InitialReposition.
A user may opt for odd or even buttons so the buttons must all be centrally located. Here again I get the central point of the container and the buttons are arranged around this. This method is also called in the ZoomContainer.Resize so that the central location of the buttons is always maintained even if the form is resized.
Above you would have seen this line
This.Parent.Reposition(This)
The Zoomcontainer.Reposition method is the one that maintains all the buttons in position.
Here I get the central point of the container and the sum of widths of the buttons. One pixel is added for each button to stop overlapping them:
nTotalWidth = oButton.Width*This.buttoncount + This.buttoncount
nCenter = THis.Width/2
nbCenter = nTotalWidth/2
nLeft = nCenter - nbCenter
Next the top of the button is calculated depending on the centrezoom property:
IF this.centerzoom
nTop = This.Height/2 - oButton.height/2
ELSE
nTop = This.Height - (oButton.Height+1)
ENDIF
Finally I iterate through all the buttons setting theme up in position:
For N = 1 To .ButtonCount
oButton = Evaluate(".zoomimage"+Transform(N))
With oButton As zoomimage
.Left = nLeft
.Top = nTop
.setupprops()
nLeft = nLeft+oButton.Width+1
.Visible = .T.
Endwith
Endfor
ZoomContainer.reposition
This method handles the repositioning of the other buttons around the zoomed one by getting a left and right value and setting each button so that the Left position of a button is one pixel to the right of the previous button. This all works very sweetly.
For aesthetics I placed a label and image in the container which is hidden at runtime.
Also I added a 3d bar to give an added perspective effect. This is just another image and is anchored to the sides of the container.
Finally the handler for the buttons. You can add any code here. The name you passed is stored in the TAG property of the button, and can be used to identify which button was clicked but really ny property can be used since I pass the button object to the method.
I looked at many icon sets but I really liked Emerson's icons so used them in the class. However you are free to use any icons you wish. I found that simple PNG's like these are the best. The more complex PNG's suffer from the VFP Flashing bug and are not recommended. Bitmaps can be used instead but PNG's give a better effect when zoomed. Just change your code to point to the icons of your choice:
.addbuttons("Name of your button","Your Icon file here","Any tooltip text")
Here 3 buttons are added
WITH This as zoomcontainer
.addbuttons("FirstButton","explorer96.png","This is the first button")
.addbuttons("SecondButton","folder96.png", "Click here for a file")
.addbuttons("ThirdButton","monitor96.png", "Monitor events")
ENDWITH
The effect is as in the naimations below depending on the centerzoom property:

The final result is as per the sample form attached in the download:
The class including source code and images can be downloaded from here.
http://www.foxite.com/downloads/default.aspx?id=176
The Green Vista bar (shown below) in the sample form above - you can select this image and “SaveAs” . It should be a BMP with a white background since PNG’s on PNG’s will cause too much flashing. It is not included in the download.

I hope you find good use for this class. If you do please drop me a line.
Cheers.
Bernard
21/12/2007 - Updated bbZoombar Class is now available for download from the attachment below. Note that this is only the class update. The main file is still available at Foxite at the link above..
This fixes a bug where only 9 buttons could be added. Now 99 buttons can be added. Thanks to Guille (Paraguay!!!) who reported this
In a previous post titled Embed Your Images, I described how you can embed images into a class.
Well in this post I will show you a better way to embed those images as well as a configuration file into a class. The class in question is a Treeview class first shown here in this post.
The class and sample forms can be downloaded from the link below.
All that is needed to use this class is to run the xmldashbuilder.scx form and configure how the Treeview will look. You can add items, link in images for embedding and set commands that will be run when a Treeview node is clicked.
Pic1 - The Builder

Pic 2 - The Builder with help

Then it is simply a matter of dropping the class on a form, sizing it and away you go.
Since you have the source you can easily open the class and see how I have done this.
Basically the TreeView is driven by a table that allows three levels for each node. This should usually be enough. Images are linked to each node and are also embedded along with the table into the class itself, so no external files are needed other than the class itself. The builder is not needed once the class has been setup. If later configuration is needed the builder must be in the same directory as the class.
You can place any commands to be run just as you do in a VFP menu. Please see the sample commands included in the class by running the builder form.
If you ever need to make changes to the configuration, then just run the builder, make them and save them. They will appear in your form the next time you run it.
Due to the requirement of the ImageList Activex, the images must be found externally, so the class will extract them automatically into the temp directory as needed at runtime. The class will not delete them so they will be “reused” if the class is used again. If needed, you can easily add this deletion of images in the Destroy of the class.
Pic 3 - The Class on a form
Part 3 – Adding and Enabling a Menu Strip
In this post I will expand on my other posts (1 & 2 ) and show how we can add a menu strip and use it from VFP. You will need to download the source code supplied in the previous post to follow along.
Mike S has requested this segment so here ya go Mike…
Open up the project in VBExpress.Net and you are good to go.
Adding a “menu strip” is very easy. Double click the file MyToolstrip.vb to open it in the design window. From the toolbox locate the MenuStrip control and select it. Click on your form to add it to the form.
For this example we will use the defaults provided same as the tool buttons. So Right Click on the MenuStrip and select “Insert Standard Items”. A standard set of menu items will be added as shown.

In the Code Window (double click anywhere on the control or from the menu View|Code), just below the last event you published, add this event:
'Please enter any new code here, below the Interop code
' these events will be published
Public Event NewDocument()
Public Event Open()
Public Event Save()
Public Event Print()
Public Event Cut()
Public Event Copy()
Public Event Paste()
Public Event Help()
Public Event ChkOnOffChanged()
' Handle all menu events here <<<--- This is what you need to add
Public Event MenuItemSelected(ByVal Menuname As String)
The final thing is to create events for each MenuClick.
To do this just double click each menu item in Design View, and this will open the code view with the click method setup. All that is needed is to paste the following line (bold) into each method:
Private Sub NewToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NewToolStripMenuItem.Click
RaiseEvent MenuItemSelected(sender.name)
End Sub
I have done this for only the File menu items. You will need to do this for all menu items.
Once that is done just rebuild the control. We have finished with VB.Net.
In VFP open your testform and see that the form control now contains the Menu items as well.

All that is needed now is to wire in the Menu handler. So in VFP, open the code window for the OleControl.MenuItemSelected. This is the new Event we exposed earlier. The code window opens with the Parameter statement already there. This is because we specified that there was a parameter to be passed by the event when we exposed this event in VB.
Add the following snippet of code.
*** ActiveX Control Event ***
LPARAMETERS menuname
LOCAL cMenu as String
cMenu = UPPER(STRTRAN(menuname,"ToolStripMenuItem",""))
IF cMenu = "EXIT"
ThisForm.Release
ELSE
WAIT WINDOW NOWAIT "You selected menu item :"+cMenu
ENDIF
Basically you have to handle the menu clicks here in one place. This can easily be achieved using a CASE…ENDCASE statement for each menu item. The name of the Menu item is passed so I just strip off the excess to reveal the menu clicked.
Now run your form and begin using the menu. Notice that Exit actually quits the form?

Thanks to Mike S for his suggestion. Actually Mike, this was on my “nextpost” list :)
Part 2 - Properties and More Events
Today I will show how we can add additional controls as well as expose properties of those controls in our Activex.
If you haven't already please read Part 1 of the post.
Open the project in vbExpress you created earlier or if you’re lazy download the complete project code from the link below and follow along.
Double click the file MyToolstrip.vb to open it in the designer. From the toolbox on the left drop a checkbox onto the usercontrol surface. Change these properties:
(Name) = chkOnOff
Autosize = True
Text = OnOff
And move it to the centre of the control as shown.

Pic1
Now we want to expose certain properties of this check box so that we can access and set them in VFP. The properties I have chosen are:
Property
Top
Left
Text (vfp Caption)
Event
Checked or not checked (VFP value)
But you can expose any properties in a similar way.
Just below the area where you declared the Public events, add these declarations as shown:
' Interop Properties code
Public Property Checked() As Boolean
Get
Return Me.chkOnOff.Checked
End Get
Set(ByVal value As Boolean)
Me.chkOnOff.Checked = value
End Set
End Property
Public Property chkTop() As Integer
Get
Return Me.chkOnOff.Top
End Get
Set(ByVal value As Integer)
Me.chkOnOff.Top = value
End Set
End Property
Public Property ChkLeft() As Integer
Get
Return Me.chkOnOff.Left
End Get
Set(ByVal value As Integer)
Me.chkOnOff.Left = value
End Set
End Property
Public Property ChkCaption() As String
Get
Return Me.chkOnOff.Text
End Get
Set(ByVal value As String)
Me.chkOnOff.Text = value
End Set
End Property
I have given them unique names so that I can find them when I add the control from VFP. If I had just used TOP then if there were more controls I would not be able to differentiate them from the TOP of other objects.
Finally we want to expose the “Changed” event so that we can trap this when the value is changed in VFP. So add this Event declaration as the last event
Public Event ChkOnOffChanged()
and after the Property declarations add this code to raise the event.:
Private Sub chkOnOff_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkOnOff.CheckedChanged
RaiseEvent ChkOnOffChanged()
End Sub
That is all. Now save and compile your project.
Note: If you have previously opened the Activex in VFP you will get a write error on build. Just close VFP and build again.
In VFP, open your test form (toolstriptester.scx from the download) and you will find the checkbox has been added.
If you open the properties window of the Olecontrol you will see that we now have an additional event and some extra properties:

Pic2
As we do in VFP we now need some control over the object. So open the INIT of the form and add this code:
Form.Init Code
WITH This as form
WITH .olecontrol1
.chkCaption = "Tick to allow data entry"
.chkTop = 35
.chkLeft = 50
ENDWITH
ENDWITH
Open the code window for the ChkOnOffChanged Event and add this code:
Olecontrol1.Chkchanged code
WAIT WINDOW NOWAIT "The value in the checkbox has been changed to :"+IIF(This.checked,".T.",".F.")
Now run your form and see that the Caption has been changed and that you have been able to re position the checkbox. You can also click the checkbox to change its value and trap this change.

Pic3
In the next post we’ll tackle exposing default and custom methods.
Have fun.
Part 1 - Installation, Control Creation & Events
Microsoft have recently released the Interop Forms Toolkit 2.0 at http://msdn2.microsoft.com/en-us/vbasic/aa701259.aspx . This toolkit allows developers to create Activex controls that can be hosted in VB as well as forms that can be called from VB. But this toolkit is not limited to VB alone. It can easily be used to create Forms and controls for use in VFP, as I will show.
First things first. Go and download the Installer from the page above. The only file you will need is InteropFormToolsInstaller.msi (5.2mb) and install it on your computer.
Now this toolkit is meant to be used with the full version of VS.NET as an ADDIN but that is something we really don’t need. The toolkit comes with some template files that will be used to do the heavy lifting in .Net. If you have the full version this will be installed as an Add-in. I use it in the free version of VBExpress.Net. which you can download from Microsoft.

Pic1
To enable the templates to appear in the Template selection in VB you will need to copy them to a particular location. So fire up explorer and navigate to the location as shown below. You need the ZIP files. VBExpress allows you to specify where it will look for your user templates.

Pic2
If you have the default directories, this will be
C:\Documents and Settings\bbout\My Documents\Visual Studio 2005\Templates\ProjectTemplates\Visual Basic\ for the templates which are :
VB6 InteropForm Library.zip
VB6 UserControl.zip
And the item templates go in
C:\Documents and Settings\bbout\My Documents\Visual Studio 2005\Templates\ItemTemplates\Visual Basic which are
VB6 InteropForm Library Info.zip
VB6 InteropForm.zip
VB6 UserControl Item.zip
Once you have done that the templates will appear in VBExpress whenever you opt for a new item.
Ok back in VBExpress select New and the New project dialog will appear. Select the VB6 Interop UserControl and rename your project as shown.

Pic3
VB Express will do its thing and create the files needed for your new user control. You now need to save the project to create the directories. So go ahead and save the project.

Pic4
One of the files created will be InteropUserControl.vb which we will rename to MyToolstrip.vb.
Pic5
Double click on it or Rt. Click and select “View Designer”. This will open the file ready for editing. From the toolbox on the left select the ToolStrip control and click on the pre-generated user control to add this control to the mix.

Pic6
The user control has no buttons so Rt. Click on it and select “Insert Standard Items”

Pic7
and standard buttons will be inserted for you..

Pic8
Now open the Code window (Rt click, “View Code”) and you will be presented with this area of code where you can add your own snippets. We need a way of exposing the events of the buttons so add the following bit of code which will create the events for each button.

Pic9
Next double click on each of the buttons in the Designer view to add an event handler as shown. Delegate the click to our newly created events. Intellisense will help.

Pic10

Pic11
That is all that is needed. You can run the control to see how it looks in VB Express. As a final step build the project and the template code will do all the work required to register the control.

Pic12
Move over to VFP. Create a new form and add an Olecontrol to it. In the dialog that will appear look for and select your control you just created and it will be added to your form.

Pic13

Pic14
Click the control and resize it to fit. Set its Anchor = 11
Now if you run the form you will see the control, but clicking any of the buttons does nothing. We need to wire in our code to handle the events we created earlier.
Double Click the control to open the VFP Code window and you will find the events we created showing up in the drop down list. Lets select the NewDocument Event first.
Pic15
and add code to handle the event when it occurs. For now just enter the code as shown.

Pic16
Do this for each of the events you created.

Pic17
Now run the form again and click the buttons. Your code will fire as shown. You have just succeeded in creating your first Interop User Control.

Pic18
Enjoy creating your .Net controls.
In my next post we will add in some other controls and expose properties. Till then have fun.
I am back from an extremely intense OzFox 2007 and I must say it was very well organised by Craig Bailey of Talman. It was great to meet other VFP users from Australia and overseas and put faces to names.
One of the sessions was Get moreProductive with VFP by Rick Schummer where he did an interactive session on enhancements we can create ourselves to make our development life easier. There were a lot of ideas brought up that were really timesavers and really cool and Rick did a really good job of describing them and the various techniques where we can save a lot of effort and time.
How many of us have these forms with objects buired deep in them. Like this sample form below:

One of the things Rick showed was how you can open a code window and Right-Click in it to bring up the menu and select "Object List" to bring up the window as shown below, where clicking on the object inserts the complete path to that object into your code.

Now while this is fine when there are a few objects it becomes very much more difficult when there are literally a thousand objects in that list. Even a few hundred would make searching that list a nightmare and make it faster to use intellisense and type in the code.
I have a solution I would like to share, that takes away all these problems and works in an instant. That is my GetObj.PRG file. In my VFPStart.prg I call this program and it resides in my VFP root folder. This hooks into the CTRL+H key combination, but you can easily change that. The code is shown below:
ON KEY LABEL
CTRL+H do getobjX in c:\vfp9\getobj.prg
* you can use HOME() if you wish
RETURN
FUNCTION
getobjX
LOCAL
bb,cc,cStr,cStrX,oldclip
bb
= SYS(1270)
cStr
= bb.name
cStrx
= ""
IF PEMSTATUS
(bb,"Value",5)
cStrx = ".Value"
ENDIF
DO WHILE
.T.
bb = bb.parent
cc=bb.name
IF
bb.baseclass = "Form"
cStr="ThisForm."+cStr
EXIT
ENDIF
cStr = cc+"."+cStr
ENDDO
oldclip
= _Cliptext
_cliptext
= cStr+cStrx
KEYBOARD
'{CTRL+V}'
_Cliptext = oldclip
RETURN
With this simple program loaded to trap the "CTRL+H" key all I have to do is
1. Click in my code window (Command, Screen/Class Code or PRG) to set the insertion point.
2. Hover the mouse over the object on the form I am interested in
3. Press "CTRL+H" to insert the code to that object wherever my insertion point was set to.
So if I had my mouse hovering over the option1. Radio button I would have this inserted into my code window in a flash:
ThisForm
.Container1.Pageframe1.Page1.Optiongroup1.Option1.Value
That is all. Takes a fraction of a second and no searching through lists or even intellisense. How cool is that?
Thanks Rick for an excellent session.
OzFox 2007 Rocked!
It has always been a problem for me to have to include images for each class as an external file. Not only is file access slow, but VFP has an irritating way of displaying the Hourglass cursor every time a file is accessed from disk. This is especially noticeable in graphical buttons that have a bitmap change for a MouseEnter and MouseLeave event.
Well not any more. Using a field in the class – the USER field, I have in one stroke removed both these irritants. Using the method described here, disk reads are eliminated and there is no need to include the bitmaps.
Note: This method only works with VFP9 since it uses the PictureVal property to load images. Also this will only work with the IMAGE base class since other objects, while they have a picture property, do not have a PictureVal property.
The method is simple. Store the bitmap into the USER field of the image class and at runtime retrieve it and assign the PictureVal property of the image object to it.
Let’s start. Create a new class – ImageXML based on the image object. For now, just save it.

I have created a simple Builder to assist in inserting the images. This is included in the download files. Feel free to improve the builder as you see fit.
Run the builder and follow the steps 1,2,3.

- Select the Picture. The image selected is displayed next to the button.
- Select the class you just created. The TextBox will display the selected class name.
There is a Button with Red writing if you want to clear out the contents of the USER field if there is any other data there. Click this button to clear it out.
3. Click the “Insert Image” button and the image is instantly inserted into the USER field of the class. Select other bitmaps (1) and append them (3). When you have inserted your images, close the builder and Browse the class as a table. In the USER field you will find lots of new data. I have used delimiters in the builder <name> and </name> <picture> and </picture> to separate the images inserted.
Please note down the images as you insert them so that you can know what they are later when you want to assign them. Close the class opened earlier as a table.
Now open your class as a class and add a new method to it – ProcessImages
Add the following code to the ProcessImages method.
* process the images
* open the class as a table
USE (THIS.CLASSLIBRARY) IN 0 ALIAS xClass SHARED
* get the field we want only
SELECT USER FROM xClass WHERE NOT EMPTY(USER) AND baseclass="image" INTO CURSOR userStr
* store the pictures
LOCAL cPixStr,nPix,cPixname,cPixContents
nPix = 1
cPixStr = ALLTRIM(USERSTR.USER)
* not needed anymore so close them off
USE IN SELECT("userstr")
USE IN SELECT("xClass")
* loop through the data extracting the images
DO WHILE .T.
cPixname = STREXTRACT(cPixStr,[<name>],[</name>],nPix)
IF EMPTY(cPixname)
EXIT
ENDIF
cPixcontents = STREXTRACT(cPixStr,[<picture>],[</picture>],nPix)
* add a property to hold this value
This.AddProperty("pix"+TRANSFORM(nPix),cPixContents)
nPix = nPix + 1
ENDDO
In the INIT of the class call the above method:
This.ProcessImages()
The image class is complete.
To test the image class, create a new form and add an instance of the ImageXML.bbImage to the form. As you can see from the above code, the images are stored in properties added at runtime, that are named pix1, pix2 etc for however many images you have inserted.
So open the INIT of the image object and add this code:
* run parent code
DODEFAULT()
* assign the PictureVal – pix1 or pix2 or pix3 etc
This.PictureVal = This.Pix1
If you are using the image object as a button and want the image to change when the Mouse enters and leaves, then in the MouseEnter add code like this:
This.PictureVal = This.pix2
And reset it in the mouse leave
This.PictureVal = This.pix1
That is all that needs to be done. No images to ship and no hourglass to be seen. This method of using images even works at runtime since the VCX is compiled into the exe and can be opened and read like a table.
As mentioned the Builder is very simple and can easily be improved. At present, with the sample code supplied, only 1 image class per classlib is supported, but by changing the ProcessImages Code, more than one image object can easily be added to the classlib.
Here is the Testform with the Images assigned:

and the large image changes as the mouse moves over it:

Google, Yahoo, Vista have all got them. Now so has Visual Foxpro and you. I am talking about those little apps called Widgets that you can use to clutter your screen with.
Using PNG graphics that are supported by VFP is one way to create very cool widgets. I have described here how PNG's with an Alpha mask can be used to show some cool glass-like pseudo "forms".
Now I will describe here how this can be extended to creating glass widgets. While we have always had widgets, and have used them, the technique described here will give you a draggable Glass Widget, similar to Vista. And best of all this can be achieved in XP!
For this post I will create a clock widget. You can download the complete source from the Attachment at the end of the post.
The clock is a simple VFP class that will autorun when dropped on a form and the form run. The trick behind the Glass effect is in the background PNG image of the class:

While it looks like a plain old black & white graphic, it contains an Alpha Channel mask embedded in it. The PNG format supports saving this mask in the image and the VFP image object respects and uses this mask. If you open this image in a paint program that supports masks, like Photoshop, (I use Paint Shop Pro) then you can see the mask.When this image is loaded into a VFP image object, the mask takes effect and makes certain areas transparent based on the information in the mask.
Thus all it takes is to insert an image object into a transparent container and the effect is complete. The clock class just adds the code for the date, year and movement of the hands. There is also code in the image class to allow dragging the container, so that the clock can be moved.Check out the code in the Mouse events of the image object class.
The clock can be instantiated in the _screen or, if you are using a top level form as the basis of your application, as I have described here and here, then this technique and class can be used.
Below you can see the Glass outer area that allows the background image to seep through. This area is also used to drag and drop the clock to a new location. The colours you can easily change since I have included the full source. Run the exe and drag the clock around. Careful when you drop it though, as we dont want to break the Glass! ![Smile [:)]](/emoticons/emotion-1.gif)
Here is the clock running inside a top level form.

C'mon get busy making your own widgets for VFP!
Vista is almost upon us with its new API’s and Aero Glass theme. It has already been shown that VFP can run in Vista and Craig Boyd has shown here how to achieve some of the glass effects of Aero in a VFP form. If you haven’t, check out: here:
http://www.sweetpotatosoftware.com/SPSBlog/PermaLink,guid,ded0ffae-4c8f-41b9-918f-b5adfe36f140.aspx
Many of us will not be updating as yet till maybe SP1 or even later since a newer more powerful computer would be needed and who has that much cash lying around in addition to the cost of Vista itself. I have searched the internet and found some sites that claim to emulate glass in XP. I even downloaded a sample in .Net that actually does show a glass effect but the form was so slow that it was impossible to be used practically. But hey, Visual FoxPro is fast. We know that. So I decided to try my hand at it.
What if I could take a form, cut out portions of it, and make the visible parts transparent and place an opaque form with objects behind it. I could then manage its placement, movement etc. On a screen it would take on the appearance of a glass form. So let’s go…
(You can download the complete source as well as the article from the attachment link at the end of the post)
Creating Mainform.scx
I start with a normal form. The form has these properties set:
BackColour = RGB(64,64,64)
BorderStyle = 0 - No Border
ShowWindow = 2 - As top level form
TitleBar = 0 – Off
The form also has some custom properties and Methods which can be seen from the sample included. The form Name is MainForm