Session E-SCRP

Using the Microsoft Script Control with VFP

Rod Paddock
Dash Point Software, Inc


This session was adapted from an article that appeared FoxTalk and is used with permission.

Introduction

Have you ever wanted to add a programming language to your Visual FoxPro applications ? If you answered yes to this question you have come to the right place. Microsoft has released an ActiveX control for adding programming languages to your VFP applications. This control is called the Microsoft Script Control.

Currently Visual FoxPro supports two constructs for adding custom scripting to your applications. You can use Macro expansion (&) or the Eval function. The problem with these constructs is they limit you to using simple commands and expressions. You cannot use more complex structures like IF/ENDIF, DO/LOOP,FOR/NEXT and calling subroutines.  This is where Visual FoxPro’s native capabilities end and the scripting control begins.

Where to find the Microsoft Script Control

The first step to using the Microsoft Scripting Control is to download and install it. The Microsoft Scripting Control can be found at www.microsoft.com/scripting. Once you have installed the scripting control you need to add an instance of the control to a form. Once you have done this you can begin using the capabilities of the control.

Tip:

 If you are interested in acquiring a VBScript reference take a look at the following URL: http://www.microsoft.com/scripting/default.htm?/scripting/vbscript/default.h

Or if you already own Visual Studio take a look at the help files that come with Visual Interdev (It includes VBScript and JavaScript references.

Scripting Control Basics

Using the scripting control is a simple as the following steps:

  1. Setting the language property. Your choices of languages are VBScript or JScript.
  2. Adding some code to the control using the AddCode method.
  3. Executing the code using the Execute Statement method.

The following code creates a basic message box function using VBScript.

#DEFINE CRLF chr(10) + chr(13)

*-- Set the language

Thisform.oleScriptingControl.Language = "VBScript"

 

*-- Add a function

Thisform.oleScriptingControl.AddCode([Function Test] + ;

            CRLF + [msgbox "hello"] + ;

            CRLF +  [ End Function ])

 

*-- Execute the function

Thisform.oleScriptingControl.ExecuteStatement("Test")

That seems pretty straight forward doesn’t it ? Now lets explain how the code works.

The first step to using the scripting control is to set the controls language property. You have two choices: VBScript and JScript. If you specify the language property as VBScript the code you add with the AddCode method must be Visual Basic Script (A subset of Visual Basic for Applications). If you specify JScript the code added must be in JavaScript.

Once you have specified the language to be used by the control you then use the AddCode method to load the control with source code to execute. The AddCode method accepts one parameter. A string that contains multiple lines of code delimited by CRLF characters.

Once you have used the AddCode method you can then run your code using the either the Run  or ExecuteStatement methods. The Run method executes functions or subroutines. The ExecuteStatement execute a single statement (like x = 1 or a simple call to a function). There is one aspect of the method described above that is rather tedious. This method requires you to code manually, delimiting each programming line with CR+LF sequences.

Wouldn’t it be nice if we had a mechanism similar to the Visual FoxPro command window. Lets create a Scripting Control testbed. Figure 1 shows our new Visual Basic command window style interface.

Figure 1. Scripting Demo Page

Manipulating FoxPro Objects With VBScript

Now for something really cool. One of the most powerful aspects of the Scripting Controls is its ability to manipulate Visual FoxPro (or Visual Basic) native objects. How can you to this you ask ? You can do this by calling the  AddObject method of the scripting control. Yes, the scripting control has a method called AddObject. The AddObject method allows you to add an object to the scripting object container. The syntax for this method consists of two parameters. The first is the name that the object will be referenced by in your VBScript or JScript code. The second parameter is a handle to your object.

To add a form to the scripting control you use the following syntax.

Thisform.oleScriptingControl.Object.AddObject(“frmFoxProForm”,Thisform)

One item you will quickly notice is the inclusion of the Object keyword. Visual FoxPro provides this property to deal with ActiveX controls that share similar properties and methods with Visual FoxPro objects.  If you attempt to call the AddObject method without the Object keyword Visual FoxPro will address the FoxPro version of the AddObject method and not the AddObject method of the scripting control.

Upon adding a reference to your Visual FoxPro object you can begin addressing the object in your VBScript using the 1st parameter of the AddObject method. The following code

Function SetFormProperties()

  If IsObject(frmFoxProForm) Then

   frmFoxProForm.Caption = "Hello World"

   frmFoxProForm.BackColor = 100000

  End If

End Function

This example demonstrates setting properties on a Visual FoxPro object. You can also call Visual FoxPro methods. The following code shows how to call the click event of a button on the scripting form.

Function CallFormMethod()

  If IsObject(frmFoxProForm) Then

   frmFoxProForm.BackColor = 400000    

   frmFoxProForm.cmdClickTest.Click()

End If

End Function

Scripting Gotchas

When developing applications using the Microsoft Scripting control there are some gotchas you need to take into account. The first deals with adding Visual FoxPro objects to the scripting control using the AddObject method. It is important to make sure the scripting control releases your controls when it is done with them. You can release your VFP controls by calling the Scripting controls Reset method. Why do you need to do this ? Dr. Watson says so. If you don't use the reset method Visual FoxPro may GPF when you release the form with the scripting control on it. The best place to put the Reset call is in the QueryUnload event of the Scripting Control's form.

Now that we are talking about Dr. Watson  there is another item to take into account. If you use ActiveX controls in your applications you need to turn FoxPro's  ActiveX Dual Interface option off. You do this by putting the following call in either your main program or in the Load method of your form. If you don’t do this FoxPro will not release your forms correctly.

Finally you for good measure it is always a good idea to call the Scripting control's Reset method after executing code. The reason for this is that the control has a tendency to become unstable if you call the AddCode method repeatedly.

Exploring Ideas

One item that comes to mind when using the scripting control is adding a custom macro language to your applications. How would you approach this ? One method of adding a macro language to your application is to store information in a table file with a memo field. This table would have the following elements:

  1. A unique ID that will be attached to a control much like a help context id.
  2. A memo field for every event you want to run code for. Name them the same as the event (Click for example).

To create this table use the following command:

CREATE TABLE myMacros (control_id I, Click m)

Select MyMacros

Index on control_id Tag control_id

Once you have built the table you can begin building  the code components to execute your macros. To do this you need do the following:

Controls that contain:

  1. Add a nControlID  property to the classes you want to add macro's to. Initialize this propety to a value of –1
  2. Add code to the proper events to call a code execution function.
  3. A function to execute the code.

The following code demonstrates adding macro abiilities to the click event of a command button:

If This.nControlId # -1

  g_runmacro(This.nControlID,"Click")

Endif

This code calls a function called g_runmacro. The g_runmacro function will look in the mymacros table for a passed in control id and run the code specified in that event. The following code represents the g_runmacro function.

Function g_runmacro(pnControlID, pcEvent)

 

*-- save the work area

Local lnSelect

lnSelect = Select()

 

*-- open the macro code table

If not used("mymacros")

  Use mymacros in 0

Endif

 

Select mymacros

Locate For control_ID = pnControlId

If Found()

 * -- get the code

 Local lcCode

 lcCode = Eval("mymacros." + pcEvent)

 

 

  *-- create a function block

  Local lcFunctionName

  lcFunctionHandle = "A" + sys(2015)

  lcBeginFunctionName = "Function " + lcFunctionHandle ;

  + chr(10) + chr(13)

  

  lcEndFunctionName = chr(10) + chr(13) + " End Function"

  lcCode = lcBeginFunctionName + lcCode + lcEndFunctionName

 

  *-- Create an automation version of the scripting control

  Local loScript

  loScript = CreateObject( "MSScriptcontrol.scriptcontrol.1")

  loScript.Language = "VBScript"

  loScript.AddCode(lcCode)

  loScript. executestatement(lcFunctionHandle)

Endif

 

Return

 Summary

Now that you have a basic understanding of using the Scripting controls you might say: "So what good does this do me?" With the scripting control you could:

You are only limited by your creativity when it comes to adding scripting to your applications. I would like to thank two people for assisting me with this session. Ken Levy for inspiring it in the first place and John Petersen for making sure my session notes would be useful for other VFP developers.