What's the deal with the VCX file?
Visual FoxPro stores all its visual classes in a file with the extension .VCX. Actually, it stores its classes in two files: The VCX and the VCT, which is a familiar combination for FoxPro programmers. Really and truly, those two files are DBF and FPT files. So you could
USE Base.vcx
BROWSE
This is useful when you want to make certain kinds of changes (like correcting typos that point 50 classes to the wrong parent class) or to fix broken VCX files (yes, it can happen). Also, there are special fields that are just there for the programmer so he can extend the VCX (see below).
The VCX structure
The VCX structure is relatively simple. Most of the information is stored in a handful of memo fields, mostly in plain English. Some of the memo fields have binary information (like compiled code or OLE information). The VCX (visual class libraries) file structure is identical to the SCX (forms) file structure.
Later in this section, I'll describe how this structure is used in different scenarios to store classes. Table 2 describes the basic structure and the meaning of the fields.
Table 2 . The VCX/SCX structure.
|
Field
|
Type |
Description |
Example |
|
Platform |
C (8) |
VCX/SCX—Used to specify the platform where this object is used. In single platform VCXes, there is one record per object. In multi-platform environments (Windows and Mac, for instance), there will be one record per platform. In this case, both records that describe the same object share the same unique ID.
|
WINDOWS |
|
UniqueID |
C (10) |
VCX/SCX—Unique ID for classes and objects. Records that describe the same object for different platforms share the same unique ID. Records that don't describe a class or object don't have unique IDs; instead, they have special keywords that describe the record type. The header record (record number 1), for instance, has the keyword "Class".
|
_QVW1055YU |
|
TimeStamp |
N (10) |
VCX/SCX—Contains the date of creation (or last modification) of this particular record in an encoded format. Records that don't describe a class or object have TIMESTAMP=0. |
498761340 |
|
Class |
Memo |
VCX/SCX—Defines the parent class if the current record is a class. If the current record describes a member object, this field defines the class for the object.
|
mycommandbutton |
|
ClassLoc |
Memo |
VCX/SCX—The relative
|
..\libs\test.vcx |
|
BaseClass |
Memo |
VCX/SCX—Contains the name of the Visual FoxPro base class that is the root of the current class (or object). |
commandbutton |
|
ObjName |
Memo |
VCX/SCX—Defines the name of the current class or member object. |
cmdOkButton |
|
Parent |
Memo |
VCX/SCX—Defines the parent object of the current object. This field is used only if the current record describes a member object.
|
form1 |
Table 2
,
|
Field Name |
Type |
Description |
Example |
|
Properties |
Memo |
VCX/SCX—Contains a list of all overwritten and new defined properties and their values.
|
Height = 22
|
|
Protected |
Memo |
VCX/SCX—Contains a list of all properties and
|
scAlias
|
|
Methods |
Memo |
VCX/SCX—Contains the source code for all methods of the current class or object. If the current record describes a subclass of a subclassed composite class that has overwritten methods for member objects (pseudo subclassing), this field might also contain code for one of the member objects of the current class. (See below for more information about pseudo subclassing and how this is stored in VCX files.)
|
PROCEDURE Click
PROCEDURE Save
|
|
ObjCode |
Memo |
VCX/SCX—Stores the compiled version of the code in the Methods field. |
|
|
Ole |
Memo |
VCX/SCX—Contains binary information about OLE and ActiveX classes and objects. |
|
|
Ole2 |
Memo |
VCX/SCX—Contains binary information about OLE and ActiveX classes and objects. |
|
|
Reserved1 |
Memo |
VCX—Used to define the beginning of a new class definition. If the current record is the beginning of a new class definition, this field contains the word "Class". Otherwise, it is empty.
SCX—Not used. |
Class |
|
Reserved2 |
Memo |
VCX/SCX—Contains the number of records that define the actual class. If the class has member objects, each member object has its own record in addition to the actual class record. The actual class record is counted as well as all the records for the member objects. So if the number is 2, this indicates a container with one member object. If the actual class doesn't have any member objects, the value of this field is 1. |
2 |
|
Reserved3 |
Memo |
VCX—Contains a list of all new defined properties and methods as well as a short description. The description is separated from the property/method name by a space. Array properties have a leading caret (^). Methods begin with an asterisk (*).
SCX—Not used. |
ScAlias
|
Table 2 , continued
|
Field Name |
Type |
Description |
Example |
|
Reserved4 |
Memo |
VCX—The relative path and file name for a bitmap that will be displayed in the Form Controls toolbar.
SCX—Not used. |
..\bmps\ok.bmp |
|
Reserved5 |
Memo |
VCX—The relative path and file name for a bitmap that will be displayed in the Class Browser.
SCX—Not used. |
..\bmps\ok.bmp |
|
Reserved6 |
Memo |
VCX/SCX—Defines the scale mode (Pixels/Foxels) for the current class or object. |
Pixels |
|
Reserved7 |
Memo |
VCX/SCX—Contains the description of the current class or object. This description can be defined in the Class Information dialog, or in the Class Browser. |
This class saves the current form. |
|
Reserved8 |
Memo |
VCX/SCX—If the current record describes a class, this field contains the relative path and the file name of a header file. If the current record is a member object and NoInit is selected in the Class Information dialog, the value of this field is "NOINIT". |
..\vfp\foxpro.h NOINIT |
|
|
Memo |
VCX/SCX—Not used by Visual FoxPro. Available for the user/programmer to extend the VCX structure. |
*:GenX |
How Visual FoxPro stores visual classes
Now you know the basic structure of a visual class library, but this isn't quite enough to understand VCXes. Every class library has a number of records, most of which define classes; others hold additional information about the library in general.
The first record of every VCX is the so-called "header record." This record gets added as soon as class libraries (including empty ones) are created. It specifies whether the current file is a class library (VCX) or a form (SCX). If it is a class library, the UniqueID is "class"; otherwise it is "screen". In addition, the Reserved1 field contains some information about the version of the class library, but this is all relatively trivial.
Once you start to add classes to a library, it gets a bit more complex. Let's start with a subclass of the Visual FoxPro base class
Custom.
This is a simple case, because custom classes don't have member objects (at least not in the visual editor). For this reason, a single record can describe this class. Refer to Table 1 to see the values of each field. Because we created a subclass of a Visual FoxPro base class, the name of the parent class is the same as the name of the base class, and the name of the class library is empty. By the way, this information is always stored in lowercase. The only other detail worth explaining is the Reserved2 field, which contains the number of records that describe the class. In this case it would be 1. This seems obvious, but a lot of people get
Let's have a look at a composite class. As an example, we'll use a form class that has an OK button as a member object. Two records can describe this construction: one for the form class and the other for the member object (the button). Still, this construction is very simple. All properties and methods belonging to the form will be stored in the first record, and all the ones
Let's take a closer look at the Methods memo. As mentioned before, this field holds the source code for all methods we create. To allow FoxPro to differentiate between different snippets, a simple solution is applied: Every method gets an additional PROCEDURE and ENDPROC line, as in the following example:
PROCEDURE Click
wait window "Test"
ENDPROC
PROCEDURE Destroy
wait window "Destroy"
ENDPROC
When you modify this code in the Visual Class Designer, Visual FoxPro does not show those two lines. The example above only has two lines of code in the Visual Class Designer.
The properties are stored in an even simpler fashion—one line per property. Here are the contents of the form record:
DoCreate = .T.
Caption = "Form2"
Name = "test"
And here we have the contents of the member object's (the button's) Property field:
Top = 84
Left = 120
Height = 23
Width = 70
Caption = "\<OK"
Name = "cmdOK"
All properties start with capital
Once we subclass our composite class, it gets a little more complex. A single record can describe the new class, even though it has the button as a member object. The definition of the member object is inherited from the parent class. This, of course, introduces some difficulties when changing properties or adding source code (pseudo subclassing), since we don't have a record in which to store these properties. The only alternative is to store this information with the container record. In this case, we have to identify the object the property or method belongs to.
The Method field from above would look like this in a subclass:
PROCEDURE Command1.Click
wait window "Click"
ENDPROC
PROCEDURE Command1.Destroy
wait window "Destroy"
ENDPROC
The same is true for the properties. Here is the Properties field of the container record:
DoCreate = .T.
Name = "test2"
Command1.Name = "Command1"
I should mention some exceptions and special cases, which are all
You could explore the previous example even further by adding subclasses and additional member objects, but you wouldn't be learning anything new. The class definitions would grow larger and more complex, but they would still follow the rules discussed above.
Knowing about the VCX file is important for various reasons. This is true for all programmers, not only for third-party tool providers and other people who might be interested in writing Class Browser add-ins. Class libraries can be damaged due to various reasons—when this happens, you can lose months of work. But often a library can be fixed easily if you know about the VCX structure. It often happens that there is a problem when saving a class—the old copy of the class might already be deleted but the new version is not yet saved. It appears that the class simply disappeared, but it is still there, marked as deleted. If you know about the VCX structure you can simply open the library and recover at least an old version of your class.
Sometimes you might want to do a large number of similar
Compiling a class library
When you modify code and close a code snippet of a visual class, Visual FoxPro compiles that code right away and stores it in the ObjCode field of the VCX, while the source code gets stored in the Methods field. Those two fields need to be synchronized at all times. When you modify the Methods field directly, opening the VCX like a DBF, you need to make sure that those changes get compiled. Otherwise you will find the funniest results when modifying the class the
COMPILE CLASSLIB MyClassLib.vcx
This works fine when you have full control over the library, but you need to be careful if you manipulate the source code using a Class Browser add-in. Compiling the class usually isn't possible because the browser is using the file. For this reason you need to close the library, compile it, and reopen it.
Cleaning up class libraries
It is essential to clean up your class libraries. They tend to grow huge, even though their real contents might be tiny. This is due to the fact that every time you modify a class, Visual FoxPro marks the old records in the VCX as deleted and adds new records at the bottom.
Cleaning up a class library is simple. You can open the VCX exclusively and do a simple PACK. This works well in most scenarios. However, I recommend using the Cleanup feature of the Class Browser (see above).
How to protect your source code in a VCX
The source code for all methods of a class is stored in the Methods field of the VCX. When this code is modified, Visual FoxPro compiles it right away and stores the compiled version in the Objcode field. This is the only version of the code that Visual FoxPro needs to instantiate the class and execute its methods. So when you want to give away a VCX library without giving away your source code, you can simply delete the contents of the Methods field, but make sure you do this on a copy of the original library. Otherwise you won't be able to modify the classes in this library anymore.