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:
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
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:
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:
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
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.