Visual Studio .NET offers a rich tool set, but anyone who has ever used Visual FoxPro will soon notice that many of their favorite features are not available.

However, a new set of public domain classes can add these functions to both Visual Basic .NET and C#.

Developers tend to be proud of their skills with a particular programming tool. This is particularly true with Visual FoxPro and Visual Basic developers. Visual FoxPro (VFP) developers are proud of their language's strong data access and string handling capabilities while Visual Basic developers are proud of their language's support of most advanced Windows technologies.

A set of classes is now available that not only help VFP developers get up to speed with .NET, but will also prove very useful for VB.NET and C# developers as well.

Visual Studio .NET is the great equalizer, though. Now, both camps suddenly find themselves staring at not one, but two new languages, both equally important and very much foreign to all. While VB developers have a little head start with VB.NET, there's still quite a learning curve. And, as most Visual Studio developers know, VFP is not part of the new Visual Studio .NET platform. While there are a number of reasons behind this (which we will not go into), and while Microsoft has stated that it will continue to support VFP, .NET is here to stay. Many old “FoxFolk,” like myself, are more than a bit curious as to what Visual Studio .NET offers, but are not too keen on giving up some of the great functionality inherent in VFP.

Fortunately, a set of classes is now available that not only helps VFP developers get up to speed with .NET, but also proves very useful for VB.NET and C# developers as well. The “VFP Toolkit for .NET,” which you can download for free from GotDotNet (http://www.gotdotnet.com/team/vfp), has 225 different functions for array handling, string manipulation, data and other operations. These functions use the same syntax as the native VFP functions. For Fox developers, this is a great tool! Steve Sawyer, a well-recognized Fox guru, put it this way, “it's like training wheels for .NET!” For other developers, though, the toolkit adds considerable functionality to their arsenal of .NET tools without the cost of development and testing. In short, the VFP Toolkit is for everyone.

What's in the VFP Toolkit?

As mentioned, the VFP Toolkit classes consist of many different functions that mimic features in Visual FoxPro. However, these are all written in .NET managed code. The toolkit is comprised of a single DLL of only 56K in size. It is a true .NET assembly, not a COM wrapper for VFP, and does not require VFP to be installed. In addition to the toolkit itself, the source code for both C# and VB.NET is also available. The toolkit ZIP file consists of a .DLL, a CHM help file, an XML dynamic help resource and a batch file for installing the toolkit. This is as complete a toolkit as you could ask for, and the development team is to be commended for the work they put into it.

The toolkit namespace consists of the following classes:

  • Arrays - Functions for manipulating arrays, including resizing, scanning, sorting, etc.
  • Common - One of two “miscellaneous” classes, which includes commonly used functions such as variable typing and value testing.
  • Dates - Various functions for setting and changing data values, including extracting date portions.
  • Dialogs - Functions for using Windows dialogs.
  • Environment - Functions for retrieving system environment information, such as disk space, printer information, window attributes, etc.
  • Files - Functions for the low-level handling of folders and files.
  • Help - The other “miscellaneous” class, including immediate IF and object creation functions.
  • Math - Functions for handling mathematic and number-related operations.
  • Strings - Functions for manipulating strings.
  • VfpData - Functions that simulate many of the VFP data handling features.

Not all of the functions contained in these classes are written totally from scratch. Many simply call the function appropriate to either VB.NET or C# (I call these “redirection” functions). The following table provides an overview of the functions (bold text indicates totally new functions while normal text indicates redirection functions).

  • Functions available only for Windows Forms, and not for Web Forms

How can the VFP Toolkit Help?

For VFP developers, the benefits from the VFP Toolkit should be obvious. The set of classes in the toolkit will help you get up to speed immediately, effectively using the same set of functions familiar to Visual FoxPro developers. Obviously, this should not be considered a replacement for similar functions already in Visual Studio .NET; in fact, the toolkit help file states if a “method maps directly to existing functionality in the .NET, use the code listed in the Implementation section of the help detail instead.” Hence the “training wheels” comparison is very close; as you become more and more familiar with the contents of VB.NET or C#, you can easily switch from VFP functions to .NET functions in many cases.

The toolkit offers 225 different functions for array handling, string manipulation, data and other operations.

As you can see from the table, however, more than half of the functions in the toolkit are totally new for Visual Studio .NET developers. The purposes behind most of them can be gleaned from their titles (see the CHM file for full descriptions and parameters) and, considering this is a free set of classes, as you review the function list I'm sure you will agree that many could be very useful. As with native Visual Studio .NET functions, some of the ones in the VFP Toolkit are overloaded; fortunately, IntelliSense will kick in when you need some coaching, and there is an XML dynamic help file included with the toolkit.

Using the VFP Toolkit

As mentioned earlier, the VFP Toolkit comes with an installation batch file. Once registered, you can begin using the VFP Toolkit like any other .NET assembly. To incorporate the toolkit into your application right-click on the References tab in the Solution Explorer and click Add Reference. If the DLL was registered properly, you should see an entry for it under the .NET tab of the Add Reference dialog box (look for the Visual FoxPro Toolkit for .NET entry in the References list). If you don't see the toolkit, click Browse, locate and select the DLL, and then click Open. This adds the toolkit to the Selected Components section of the Add Reference dialog box. Click OK and you are ready for the next step, which is to add the namespace to your code.

Now that you have added a reference to the toolkit, you can begin using it in your applications. In order to use the toolkit you need recognize some fundamental differences between VB.NET and C#. For VB.NET, you have two options: the first is to add toolkit classes through the Solution Explorer. To do this, right-click on your project and click Properties to display the Property Pages dialog box. Then, click the Imports option under Common Properties. Type the name of each class you want to include in your project into the Namespace box, and then click Add Import.

The other option is to do it directly in code (remember, there's code for everything in .NET!). Add it to the top of your class or form, like this:

Imports VFPToolkit
Imports VFPToolkit.vfpData
Imports VFPToolkit.strings

For C# developers, there are no dialog boxes; you'll have to add the namespace in code (but hey, you're a C# developer, who needs dialog boxes anyway?) You can either include the entire assembly:

using VFPToolkit;

Or include only selected classes:

using VfpData = VFPToolkit.vfpData;
using VfpStrings = VFPToolkit.strings;

To illustrate how to use VFP Toolkit functions in your project, I've constructed a simple Windows form in VB.NET that uses three of the many functions available: GetWordCount*(),* which counts the number of words in a string; Lower*(),* which is a redirection function to change a string to lower-case; and Browse*(),* which displays a form with data from a table. Figure 1 shows the form itself. Figure 2 shows the form launched by the Browse button. Listing 1 provides the code behind the sample form. For simplicity, I removed the Windows form designer code from Listing 1 and bolded the lines that call the various toolkit functions.

Figure 1: A sample form with controls that use three of the VFP Toolkit functions.
Figure 1: A sample form with controls that use three of the VFP Toolkit functions.
Figure 2: The “Browse” function, triggered by a button on the sample form, launches a separate form to show the data. This form is included in the toolkit.
Figure 2: The “Browse” function, triggered by a button on the sample form, launches a separate form to show the data. This form is included in the toolkit.

The C# code is somewhat similar, as shown in Listing 2. Again, I removed the Windows form code.

These are simplistic examples, but I hope they are enough to get you interested in checking out the VFP Toolkit. Considering how much work has been done for you, and the fact that this is public domain software, the toolkit is a steal for what it provides. For example, Listing 3 shows the code behind the GetWordCount function (in C#).

This is as complete a toolkit as you could ask for… and did I mention that it is free?

Have another look at the table of toolkit functions and I think you will appreciate what this set of classes can bring to your application. Imagine trying to code all of those from scratch on your own.

Under the Hood of the VFP Toolkit

The VFP Toolkit classes are built into what is called an assembly. In Visual Studio .NET, assemblies provide flexibility when dealing with issues like security, version control (including side-by-side execution of differing versions) and debugging. Assemblies are the basic building blocks of a remotely deployable application, as only the ones required for startup need to be present for the application to run. Any other required assemblies are retrieved on demand, which keeps the initial deployment costs low.

The VFP Toolkit is an example of a static assembly. A static assembly is one that is already defined and contains all of the resources it may require (bitmaps, JPEGs, resource files, etc.). .NET can also construct dynamic assemblies, which are built at run-time and can be saved to disk after execution.

Assemblies can also have various compositions. VB.NET and C# projects can be compiled into single-file assemblies (where the code module has a single entry point) or as library assemblies. Library assemblies, like class libraries, have components (types) that can be called by other assemblies, but have no entry point.

Assemblies can also be constructed as multi-file assemblies. This is useful if you have multiple code modules under development by different developers, written in different languages, or you need to construct an application that can be downloaded via the <object> tag in IE. Multi-file assemblies must be compiled using the command-line compilers or Visual Studio .NET with the Managed Extensions for C++.

Considering how much work has been done for you, and the fact that this is public domain software, the toolkit is a steal for what it provides.

At a minimum, an assembly must contain type information and implementation (class definitions and the code that goes with them) as well as an assembly manifest. This is the metadata that describes how the elements of an assembly relate to each other. An assembly manifest contains the assembly name, its version number, culture (language-specific information, and only required when building satellite assemblies), strong name information (public key information from the publisher, if given a strong name), a list of files in the assembly, type reference information and information on referenced assemblies. An example of this information is in the AssemblyInfo.cs portion of the VFPToolKitNet_CSharpNET_Source project, a portion of which is reproduced here:

[assembly: AssemblyTitle("Visual FoxPro Toolkit for .NET")]
[assembly: AssemblyDescription("Visual FoxPro Toolkit for .NET")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Team: Kamal Patel, Cathi Gero, Rick Hodder, Nancy Folsom, Ken Levy")]
[assembly: AssemblyProduct("Visual FoxPro Toolkit for .NET")]
[assembly: AssemblyCopyright("Public Domain (none)")]
[assembly: AssemblyTrademark("-")]
[assembly: AssemblyCulture("")]

The command-line compilers for creating an assembly are fairly straightforward. Once you are ready to turn a module into an assembly, execute the following for a single-file assembly:

&lt;compiler command&gt; /out:&lt;file name&gt; &lt;module name&gt; 

Or the following for a library assembly:

&lt;compiler command&gt; /t:library &lt;module name&gt;

So to create a library assembly from a VB.NET module, you execute this:

vbc /out:myCodeLibrary.dll /t:library myCode.vb

For more information on assemblies, refer to the Visual Studio .NET help.

A Great Set of Tools for a Great Price

For VFP developers and anyone else wanting to learn .NET and add functionality to their developmental toolbox, the VFP Toolkit is a great resource. Again, this is public domain software, which you can download from GotDotNet (http://www.gotdotnet.com/team/vfp). Check it out, and I think you'll agree that this is a must-have set of classes for your application.

Listing 1: VB.NET Winform with VFP Toolkit Functions


Imports VFPToolkit
Imports VFPToolkit.vfpData
Imports VFPToolkit.strings
Imports System.Data
Imports System.Data.DataSet
Imports System.Data.OleDb

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "
.
.
.
#End Region

    Private Sub TextBox1_TextChanged(ByVal sender _
        As System.Object, ByVal e As _
        System.EventArgs) Handles TextBox1.TextChanged

        TextBox2.Text = Lower(TextBox1.Text)
    End Sub

    Private Sub Button1_Click(ByVal sender As _
      System.Object, ByVal e As System.EventArgs) _
      Handles Button1.Click
        'Establish a connection and a command 
        Dim lcConnectionString As String
        Dim lcSQL As String
        Dim oConn As OleDbConnection
        Dim goView As DataView

        'Get the connection string and sql statement
        lcConnectionString = "Provider=vfpoledb.1;" + _
          "Data Source=" + _
          "'C:\Program Files\Microsoft Visual FoxPro" + _
          " 7\Samples\Data\testdata.dbc'" + _
          ";password='';user id=''"
        lcSQL = "Select * from customer"

        'Connect to the Database, execute the query and
        ' disconnect
        'note since we Import the VFPToolKit.vfdData 
        'above, we don't have to preface the 
        'SqlConnect(), SqlExecute(), SqlDisconnect() 
        'commands

        oConn = SqlConnect(lcConnectionString)
        goView = SqlExecute(oConn, lcSQL, "CustomerList")
        SqlDisConnect(oConn)

        'Select the default cursor ? note SELECT is a 
        'VB.NET reserved word so we need to preface
        vfpData.Select(goView)
        Browse()

    End Sub

    Private Sub Button2_Click(ByVal sender _
      As System.Object, ByVal e As System.EventArgs) _
      Handles Button2.Click

        Dim liWordCount As Integer
        liWordCount = _
          strings.GetWordCount(TextBox3.Text)
        'We'll use the native ToString function ? could 
        'also use the VFPToolkit.Strings.STR()	  
        Label2.Text = liWordCount.ToString()
    End Sub

Listing 2: C# Winform with VFP Toolkit Functions

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.OleDb;
using VFPToolkit;

namespace VFP_Toolkit_test_in_C_Sharp
{
   /// &lt;summary&gt;
   /// Summary description for Form1.
   /// &lt;/summary&gt;
   public class Form1 : System.Windows.Forms.Form
      {
      /// The main entry point for the application.
      /// &lt;/summary&gt;
      [STAThread]
      static void Main() 
      {
         Application.Run(new Form1());
      }

      private void Button2_Click(object sender,
         System.EventArgs e)
      {
         long liWordCount;
         liWordCount =  
         strings.GetWordCount(TextBox3.Text);
         Label2.Text = liWordCount.ToString();
      }

      private void TextBox1_TextChanged(object sender,
         System.EventArgs e)
      {
         TextBox2.Text = 
         strings.Lower(TextBox1.Text);
      }

      private void Button1_Click(object sender, 
         System.EventArgs e)
      {
         string lcConnectionString;
         string lcSQL;
         OleDbConnection oConn;
         DataView goView;

         lcConnectionString = 
            "Provider=vfpoledb.1;Data Source=" + 
            "'C:\\Program Files\\" + 
            "Microsoft Visual FoxPro 7\\" +		"Samples\\Data\\testdata.dbc'" +
            ";password='';user id=''";
         lcSQL = "Select * from customer";

         //Connect to the Database, execute the query and 
         // disconnect
         //SqlConnect(), SqlExecute(), SqlDisconnect() 
         // must be prefaced in C#
         oConn =
         vfpData.SqlConnect(lcConnectionString);
         goView = vfpData.SqlExecute(oConn,
           lcSQL, "CustomerList");
         vfpData.SqlDisConnect(oConn);

         //Select the default cursor and browse it
         vfpData.Select(goView);
         vfpData.Browse();

      }
   }
}

Listing 3: The GetWordCount Function


public static long GetWordCount(string cString)
{
   int i = 0 ;
   long nLength = cString.Length;
   long nWordCount = 0;

   //Begin by checking for the first word
   if (!Char.IsWhiteSpace(cString[0]))
   {
      nWordCount ++;
   }
   //Now look for white spaces and count each word
   for ( i=0 ; i &lt; nLength ; i++ )
   {
      //Check for a space to begin counting a word
      if (Char.IsWhiteSpace(cString[i]))
      {
         //We think we encountered a word
         //Remove any following white spaces if
         //any after this word
         do
         {
            //Check if we have reached the 
            //limit and if so then exit the loop
            i ++ ;
            if (i &gt;= nLength) {break;}
            if (!Char.IsWhiteSpace(cString[i]))
            {
               nWordCount++;
               break;
            }
         } while (true);
      }
   }
   return nWordCount;
}

ArraysACopy, ADel, ADir, AFont, AIns, ALen, ALines, APrinters, AScan, ASort
CommonBetween, CPConvert, CPCurrent, Empty, GetPEM, InList, IsBlank, IsNull, KeyBoard*, NVL, Parameters, PCount, RGB, Type, Vartype
DatesCDOW, CMonth, CTOD, CTOT, Date, DateTime, Day, DMY, DOW, DTOC, DTOS, DTOT, GoMonth, Hour, MDY, Minute, Month, Quarter, Sec, Seconds, Time, TTOC, TTOD, Week, Year
DialogsGetColor*, GetDir*, GetFile*, GetFont*, GetPict*, GetPrinter*, LocFile*, MessageBox*, PutFile*
EnvironmentCapsLog, DiskSpace, DriveType, GetEnv, ID, InsMode, IsMouse*, NumLock, OS, PrintStatus*, PrtInfo*, Sys, SysMetric*, Version, WBorder*, WDockable*, WFont*, WMaximum*, WMinimum*, WOnTop*, WParent*, WTitle*, WVisible*, _ClipText*, _DblClick
FilesAddBS, AGetFile, CurDir, DefaultExt, Directory, DisplayPath, FChSize, FClose, FCreate, FDate, FEOF, FFlush, File, FOpen, ForceExt, ForcePath, FPuts, FRead, FSeek, FTime, FullPath, FWrite, Home*, JustDrive, JustExt, JustFName, JustPath, JustStem
HelpCreateObject, CreateObjectEX, Do, DoDefault, EditSource, GetInterface, GetObject, IIF, NewObject, _Screen
MathAbs, ACos, ASin, ATan, Atn2, BitAnd, BitLShift, NitNot, BitOr, BitRShift, BitTest, Ceiling, Cos, DTOR, Exp, Floor, Int, Log, Log10, Max, Min, Mod, MTON, NTOM, Pi, Random, Round, RTOD, Sign, Sin, Sqrt, Tan
StringsAllTrim, Asc, At, AtC, AtCLine, Chr, ChrTran, CreateBinary, FileToStri, GetWordCount, GetWordNum, IsAlpha, IsDigit, IsLower, IsUpper, Left, Len, Lower, LTrim, MemLines, MLine, Occurs, PadC, PadL, PadR, Proper, RAt, RAtLine, Replicate, Right, RTrim, Space, Str, StrExtract, StrToFile, StrTran, Stuff, SubStr, Trim, Upper, Val
VfpDataAlias, AppendBlank, BOF, Browse*, Count, CursorToXML, CurVal, Delete, DeleteAll, Deleted, DeleteFor, Descending, EOF, FCount, Field, Filter, Found, IndexSeek, IsReadOnly, Lookup, Order, Recall, RecCount, Seek, Select, Set, SetFilterTo, SetOrderTo, SqlConnect, SqlDisconnect, SqlExecute, SqlStringConnect, XMLToCursor