® Microsoft® Visual FoxPro for Windows Versions: 3.0 Subject: Components of a Customized Builder Contents: 11 Pages, No Disk Product Support Services Application Note 12/95 FW1223 INFORMATION PROVIDED IN THIS DOCUMENT AND ANY SOFTWARE THAT MAY ACCOMPANY THIS DOCUMENT (collectively referred to as an Application Note) IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. The user assumes the entire risk as to the accuracy and the use of this Application Note. This Application Note may be copied and distributed subject to the following conditions: 1) All text must be copied without modification and all pages must be included; 2) If software is included, all files on the disk(s) must be copied without modification (the MS-DOS® utility diskcopy is appropriate for this purpose); 3) All components of this Application Note must be distributed together; and 4) This Application Note may not be distributed for profit. Copyright © 1995 Microsoft Corporation. All Rights Reserved. Microsoft, MS-DOS, FoxPro, and Windows are registered trademarks of Microsoft Corporation. This document was created using Microsoft Word for Windows®. Table of Contents INTRODUCTION ........................................................................................................................................................ 1 Overview of the Builders that Ship with Visual FoxPro ....................................................................................... 2 Characteristics of a Builder ................................................................................................................................. 3 Components of the Builder Application ............................................................................................................... 4 Step-by-Step Example of a Custom Builder ....................................................................................................... 5 Developing a Custom Builder.................................................................................................................................. 8 How to Register a Builder ................................................................................................................................... 8 Registering a Builder Using the BUILDER.DBF Table ................................................................................ 8 Registering a Builder Using the Builder Property ........................................................................................ 9 How to Call the Builder Application Under Program Control ............................................................................... 9 How to Reference a Selected Object .................................................................................................................. 9 How to Read Properties from the Property Sheet ............................................................................................... 9 How to Write Method Code for the Selected Control ........................................................................................ 10 Other Methods Useful in Developing a Builder ................................................................................................. 10 Hints and Commonly Asked Questions ............................................................................................................... 11 INTRODUCTION A builder is a tool provided by Visual FoxPro for Windows to assist users in the design of objects. The tool presents a series of choices that set properties used in building an object. A builder allows you to quickly design a form by simplifying the process of setting properties for controls. A builder is similar in concept to a Wizard. Both are essential components of Rapid Application Development (RAD), but they differ in their implementation. The goal of a Wizard is to take you step by step through a process to accomplish a common task, whereas a builder lets you adjust the attributes of existing objects at design time. Visual FoxPro ships with 10 predefined builders: the Edit Box builder, the Option Group builder, the List Box builder, the Grid builder, the Form builder, the Combo Box builder, the Command Group builder, the AutoFormat builder, the Text Box builder, and the Referential Integrity builder. You can call a builder interactively from the shortcut menu in the Form Designer or the Visual Class designer, the Builder button in the Property sheet, or the Builder Lock button in the Form Control toolbar. You can also call the builder from the Command window with a DO command. To set preferences for the Builder Lock button, click the Forms tab in the Options dialog box. In addition to providing these existing builders, Visual FoxPro offers an open architecture that allows a developer to register and develop new custom builders. Overview of the Builders that Ship with Visual FoxPro Microsoft Product Support Services Components of a Customized Builder Page 2 The following table lists the builders shipped with Visual FoxPro. The first column lists the builder, the second column provides a short description of the builder; the third column documents the characteristics of the control that the builder modifies, and the fourth column lists properties that are changed when the attribute is modified. Builder Description Characteristics Edit Box Creates and sets properties for an EditBox control. Format Style List Box Creates and sets properties for a ListBox control. Grid Creates and sets properties for a Grid control. Combo Box Command Group AutoFormat Creates and sets properties for a ComboBox control. Creates and sets properties for buttons in a command group. Applies a style to selected controls on a form. Value List Source Style (3D) Dimensions Incremental Searching Column Layout Return Value Source Data Stored Location Grid Source Presentation Style Column Layout Column Control Type Source Data Relationship List Source Style (3D) Combo or List Incremental Searching Column Layout Return Value Source Data Stored Location Number of Buttons Captions Graphics Horizontal or Vertical Layout Spacing Border Style Border Colors Fonts Layout 3D Effects Microsoft Product Support Services Noteworthy Corresponding Properties AllowTabs, Scrollbars,ReadOnly, Format, Enabled, HideSelection SpecialEffect, Alignment, BorderStyle ControlSource RowSourceType, RowSource BoundColumn RecordSource SpecialEffect Width ControlSource RelationalExpr RowSourceType, RowSource IncrementalSearch ButtonCount Caption BorderStyle BackColor, Forecolor, BorderColor BackStyle Components of a Customized Builder Option Group Page 3 Creates and sets properties for buttons in an option group. Form Adds controls to a form using fields and a style the user specifies. Referential Integrity Creates triggers and stored procedures that enforce referential integrity between tables in your database. Number of buttons ButtonCount Standard or Graphical Appearance Horizontal or Vertical Layout Spacing between Buttons Data Source Presentation Style Horizontal or Vertical Layout Multiple Column Options Data Source Rules for Updating Rules for Deleting Rules for Inserting Style BorderStyle CREATE TRIGGER command Characteristics of a Builder A builder interface is usually a tabbed dialog box, and lets the user set attributes of an object. Builders are usually used with Form objects, but they are not limited to visual objects. If you want to develop a customized builder, you should consider the following design goals: Characteristic Description Simplicity A builder presents a set of properties to the user in a logical way. Users should be able to modify these properties easily. A builder is typically used to build controls, but you can use it to construct the properties of a non-visual object as well. Ability to modify objects at design time A builder is used at design time and immediately modifies the properties of a selected object. Ability to cancel changes A user should be allowed to cancel the changes that have been made. Therefore, a builder should save the initial state of an object when it is accessed. Reentrant builder Users should be able to invoke the builder at any time. The same builder can be used several times to build an object. When the builder is started, it takes the state of the object at start up time. Modality All the builders shipped with Visual FoxPro use modal dialog boxes. With this design, the Command window and the rest of the product cannot be accessed while the builder is running. Using modal dialog boxes removes complexity from your application. Error handling Builders should have a routine that processes potential errors. Microsoft Product Support Services Components of a Customized Builder Page 4 Components of the Builder Application BUILDER.APP This is a Visual FoxPro application that serves as a main driver for a builder program. Its main purpose is to locate the appropriate routine to run among the registered builders, and start it. All builders that interface with the form use this application. The Referential Integrity builder uses a different engine, which is not discussed here. _BUILDER This system memory variable points to the application that controls the builders. When you install a builder, it is set by default to BUILDER.APP. If you decide to write another driver program, you must modify the content of this variable. BUILDER.DBF This is the table that stores the registration of existing builders and is an essential part of the application. The table is by default installed in the Wizards directory off the main Visual FoxPro directory. This table has the same structure as the Wizard.dbf table. Field Type Dec NAME DESCRIPT BITMAP TYPE PROGRAM CLASSLIB CLASSNAME PARMS Name Character Memo Memo Character Memo Memo Memo Memo Width 45 20 The Name field contains the name you give to the builder. This field cannot be empty. The Descript field contains a description of the builder. The Bitmap field is not used by the builder application. The Type field is the basis of the builder application. It stores the type of object that calls the builder. When the builder application is invoked, it looks at the Class and the BaseClass properties of the object, and compares it with the content of the Type field. For example, the Type field holds the value COMMANDBUTTON for a command button builder. The AutoFormat builder uses the MULTISELECT value because it is run against multiple selected controls. When the builder application compares the Type field and the class of the object, the appropriate routine is started if there is a match. If there is no match, an alert is displayed that indicates there is no registered builder. If there are several builders suitable for the class, the following dialog box is displayed. Microsoft Product Support Services Components of a Customized Builder Page 5 The Program field holds the name of any specific program or application that is started with the builder. This field is blank for all the builders shipped with Visual FoxPro because they were developed as classes. The ClassLib and ClassName fields hold the name of the Visual Class Library (.VCX) and the class corresponding to the builders. The builder application creates an instance of the class when it is invoked. The Parms field lists additional parameters passed to the builder program. By default, the BUILDER.APP application passes three parameters to a builder program: The first parameter is the string wbReturnValue. You can use this parameter if your customized builder needs to return a value to a higher level program. WbReturnValue is the name of the memory variable in the builder application that the builder should update with the value that is returned by BUILDER.APP. The second parameter is the string from the Parms field in the BUILDER.DBF registration table. The literal string is passed to your customized builder program. For example, if the Parms field contains the value CmdButtonOnly, the builder program receives this string as a parameter. The third parameter contains optional information that might have been passed to the BUILDER.APP builder application. For example, certain keywords such as NOUI might be passed to BUILDER.APP to specify that the builder should be run without a user interface. This option is also passed to the custom builder program. Your Customized Builder Program The builder application provides hooks that allow you to develop and register your program as a builder for a specific control or group of controls. Your program provides an interface to the user, and modifies the properties of the selected items. In the rest of this document, the "builder application" refers to the driver program, BUILDER.APP. The "builder program" refers to the custom builder or the specific interface that modifies the properties of a control. Step-by-Step Example of a Custom Builder This section provides a step-by-step example that shows how to build and register a custom builder from start to finish. The purpose of this exercise is to introduce you to custom builders with a simplified working program. The sample program provides a way to change the font of all selected controls. Please note that because this example has been kept as simple as possible, it does not contain an error routine. However, a real-world custom builder will likely include an error routine. 1. Verify that the _BUILDER builder system memory variable points to the correct application. By default: _BUILDER="C:\VFP\BUILDER.APP" 2. Write your custom builder program, which provides an interface and modifies the properties of the selected control. The following sample program presents the font selection dialog box to the user, and changes the FontName, FontBold, and FontItalic properties of the selected control. Copy and paste this code to a program called CHGFONT.PRG and save it to the VFP\WIZARDS directory. LPARAMETERS tobject, tsource, txt LOCAL nNumberOfObjects, cNewFont, cNewFontName, cNewFontSize,cNewFontStyle LOCAL ARRAY atest(1,2) nNumberOfObjects=ASELOBJ(atest) cNewFont=GETFONT() IF NOT EMPTY(cNewFont) cNewFontName=SUBSTR(cNewFont,1,AT(',',cNewFont)-1) cNewFontSize=SUBSTR(cNewFont,AT(',',cNewFont)+1,(AT(',',cNewFont,2)-; AT(',',cNewFont)-1)) cNewfontstyle=SUBSTR(cNewFont,AT(',',cNewFont,2)+1) FOR i=1 TO nNumberOfObjects Microsoft Product Support Services Components of a Customized Builder Page 6 IF INLIST(atest(i).BaseClass,"Checkbox","Column","Combobox",; "Commandbutton","Editbox","Grid", "Label","Listbox",; "Optionbutton", "Page", "Spinner","Textbox" ) * Verifies that the control has a fontname property atest(i).FontName=cNewFontName atest(i).FontSize=VAL(cNewFontSize) DO CASE CASE cNewfontStyle=="N" atest(I).FontBold=.F. atest(I).FontItalic=.F. CASE cNewFontStyle=="B" atest(I).FontBold=.T. atest(I).FontItalic=.F. CASE cNewFontStyle=="I" atest(I).FontBold=.F. atest(I).FontItalic=.T. CASE cNewFontStyle=="BI" atest(i).FontItalic=.T. atest(i).FontBold=.T. ENDCASE ENDIF ENDFOR ENDIF The ASELOBJ() function places object references to currently selected controls in the active Form Designer into a memory variable array. 3. The next step is to register your custom builder by adding a record to the BUILDER.DBF table. To achieve this: a. Open the BUILDER.DBF table, located in the WIZARDS directory off the main Visual FoxPro directory. b. BROWSE the table and APPEND a new record. You can press CTRL+Y to append a record. c. Enter the following values for the following fields: Name: The Builder That Changes Fonts Descript: This builder modifies the font of all selected controls. Type: MULTISELECT. This type specifies that the builder is invoked when several objects are selected. Program: CHGFONT.PRG The BROWSE window should appear as follows: Your custom builder is now registered. 4. To use the builder, create a form, and then place two text boxes, two check boxes, and a command button on the form. Modify the caption of the check boxes to Bold for the first check box, and Italic for the second check box. Type RELEASE THISFORM in the Click event handler for the command button. Your form should appear as follows: Microsoft Product Support Services Components of a Customized Builder Page 7 5. Select two controls and right-click the form. From the shortcut menu, select Builder. Because there are two builders with the MULTISELECT type, the following dialog box is displayed. Select "The Builder That Changes Fonts." 6. The GETFONT dialog box is displayed. Select Arial, Italic, 12, and click OK. You are returned to the form, which should look as follows: Microsoft Product Support Services Components of a Customized Builder Page 8 Developing a Custom Builder The builder application, BUILDER.APP, can run your customized builders. These can be registered as programs or class libraries. If they are registered as programs, BUILDER.APP runs the program. If your customized builder is a class library, BUILDER.APP creates an instance of the class. This section discusses what to consider when writing a builder, and functions and methods you can use to reference objects and their properties. How to Register a Builder You can register a builder using the BUILDER.DBF table or the Builder property. Registering a Builder Using the BUILDER.DBF Table You can add a record to the BUILDER.DBF table located in the WIZARDS directory off the main Visual FoxPro directory to register your builder. There is one record per builder. The structure of the table is detailed in the COMPONENTS section. The following two entries in the table are essential: The Type field contains the class of the object that should invoke the builder. If you create a builder that you want to start after multiple objects have been selected, store the MULTISELECT value in the Type field. If the Type field is empty, the builder is never invoked. Conversely, if a builder is registered with the ALL type, it is always started. One of the following fields must have a value: The Program field contains the name of the program to execute. This can be a PRG, a FXP, an APP or an EXE. To run the correct program, BUILDER.APP requires that the extension be specifically added to the filename in the Program field. This field can be empty if the ClassLib and ClassName fields are filled. The ClassLib and ClassName fields contain the class library and class names of the builders. This is the approach used with the builders shipped with Visual FoxPro. If both the Program and ClassLib fields are empty, the error "There are no registered builders of this type" is displayed when you attempt to start the builder. When both the Program and the ClassLib fields contain a non-blank value, the program takes precedence and is run. If you do not specify a path to the program or the visual class library, BUILDER.APP looks for the custom builder in the following order: 1. The WIZARDS directory 2. The default directory set with the CD or the SET DEFAULT commands 3. The Visual FoxPro directory Microsoft Product Support Services Components of a Customized Builder Page 9 4. The Visual FoxPro path set with the SET PATH command. Registering a Builder Using the Builder Property You can bypass BUILDER.DBF and create a custom property called Builder. This property of a control holds the name of the builder program. If you are using a builder for a control on a form, this method requires that you create a class for the object that will use the builder, because it is not possible to create a new property for a control on a form. The following step-by-step procedure illustrates how to register a builder using the Builder property. 1. Create a class by typing CREATE CLASS in the Command window. Give a name and a base class to your class. 2. Once the Class Designer is displayed, click New Property on the Class menu. 3. Name the Property Builder. 4. In the Property sheet, select the Builder property and type the name of your customized builder program. When you place the custom control on the form, you can invoke the builder when the control is dragged onto a form if the Builder Lock is on, or by right-clicking the property sheet. How to Call the Builder Application Under Program Control In addition to the interactive ways to call a builder listed at the beginning of this document, you can call it as follows: DO (_BUILDER) WITH <Parameter list> Regardless of the driver program used, Visual FoxPro passes two parameters to the builder program. The application needs to include a PARAMETERS statement with the following information: 1. The first parameter is a reference to the object selected when the builder is called. 2. The second parameter is a reference to the origin of the call. This parameter can take the following values: Rmouse if the builder is called from the shortcut menu displayed by right-clicking the object. Psheet if the builder is called from the Builder button. ToolBox if the builder is called from the Builder button in the Form Controls toolbar. How to Reference a Selected Object If you are working in the Form Designer, a typical scenario is to select one or more controls and invoke the builder from there. The ASELOBJ( ) function places object references to currently selected controls in the active Form Designer into a memory variable array. You can then manipulate the elements of the array in your customized driver. This allows you to have a generic reference to the objects and select a variable number of objects. For example, use the following to change the background color of all selected objects: nNumberOfObjects=ASELOBJ(aObjSelect) FOR i=1 TO nNumberOfObjects aObjSelect(i).BackColor=RGB(255,0,0) ENDFOR How to Read Properties from the Property Sheet On occasion, the builder program needs to read, and not evaluate, the literal expression that is associated with a property in the property sheet. Reading the expression might be necessary to create a reentrant builder. The ReadExpression method returns the expression entered for a property value in the Properties window. For example, suppose you are developing a builder for an alert box. This builder defines a container with a text box that contains an expression. You want to base this expression on a variable. The builder does not modify the Microsoft Product Support Services Components of a Customized Builder Page 10 state of the object, or the expression, until the user instructs it to. Using this scenario, you can use the ReadExpression method in the following manner: 1. The Value property for the text box reads: Value: =cMessage. 2. The variable cMessage holds a message: cMessage="This is an error" 3. Assuming that the text box is the selected object, and a reference of the object has been stored in the aSelectedObject array, you can use the ReadExpression method to retrieve the literal expression. For example: cExpression=aSelectedObject(1).ReadExpression('Value') IF NOT EMPTY(cExpression) THISFORM.TextBox.Value=cExpression ELSE THISFORM.TextBox.Value=aSelectedObject(1).Value ENDIF cExpression=aSelectedObject(1).ReadExpression('Value') The complementary method to ReadExpression is the WriteExpression method. It allows you to write an expression to a property at design time. How to Write Method Code for the Selected Control There might be circumstances that require modifying the method code in addition to setting property values. The ReadMethod and WriteMethod methods allow you to read and write method code for the specified object. These methods are available only at design time. The syntax for ReadMethod is Control.ReadMethod(cMethod). For a list of objects that use the ReadMethod method, refer to the online Help file for Visual FoxPro. The syntax for WriteMethod is Control.WriteMethod(MethodName, MethodText). For example, suppose you are writing a command button builder and you need to write code that releases a form when a user clicks a command button. You need to add the method code to the click event of a command button, without overwriting the existing code. The following steps provide an outline on how to achieve this functionality: 1. Get a reference to the selected object. nNumberofObjects=ASELOBJ(aCmdSelect) 2. Retrieve the content of the code already in the Click method. cClickCode=READMETHOD(aCmdSelect(1), "Click") 3. Add code to the method: cClickCode=cClickCode+CHR(3)+ 'RELEASE THISFORM' Note that the WriteMethod method only writes to existing methods. It is not possible to create a new method with it. Other Methods Useful in Developing a Builder CloneObject The CloneObject method duplicates an object, including all the object's properties, events, and methods. You can use the CloneObject method at startup time to make a backup of the selected object. For example: nNumberOfSelected=ASELOBJ(THIS.aCtrlSelected) =ASELOBJ(THIS.aContainer,1) THIS.aCtrlSelected(1,1).CloneObject('oNewObject') THIS.aContainer(1).oNewObject.Top= ; THIS.aContainer(1).oNewObject.Top-1000 Microsoft Product Support Services Components of a Customized Builder Page 11 In this example, aCtrlSelected and aContainer are array properties defined at the class level (form). AddObject The AddObject method adds an object to a container object at run time. RemoveObject The RemoveObject method removes a specified object from a container object. If, for example, you have duplicated an object and want to remove the temporary object when a user clicks the OK button, you can use the following syntax: THISFORM.aContainer(1).RemoveObject(ThisForm.aContainer(1).oRef.name) SaveAsClass The SaveAsClass method saves an instance of an object as a class definition in a class library. SaveAs The SaveAs method saves an object as an SCX file. Hints and Commonly Asked Questions 1. 2. Q. I get the error "not enough parameters" when my builder program is started. I keep adding parameters to the builder program, but I still receive the error when the builder is started. How many parameters does my customized builder program need to have? A. Your customized builder program should accept at least three parameters. If you have three parameters and keep receiving the same error message, the builder program might still be in memory. Issue a CLEAR PROGRAM or delete the compiled program to force a recompile before you invoke the builder. Q. I have registered my builder as a VCX. When I call it from a form, the dialog box I have created comes up, then goes away. A. The BUILDER.APP creates an instance of the class you have created, but this instance variable does not have public scope. When the form is created, the instance variable is initialized. It then goes out of scope, and then is released, along with the form. Make the form modal to prevent code from being executed until you release the form. To define a modal window, modify the WindowType property as follows: WindowType=1-Modal 3. Q. How do you hide the Property sheet? A. Issue the following command to hide the Property sheet: HIDE WINDOW Property 4. Q. I receive an error message "The specified builder was not found" when I invoke my customized builder. However, my builder program seems to be correctly registered in BUILDER.DBF, and I am sure the program is located in the correct directory. A. Verify that the entry in the Program memo field does not contain a carriage return and line feed, which creates an additional line. To verify that the program field does not contain an additional line, open the memo field and select Edit, Select All to highlight the content of the memo field. If there is an extra line, remove it. Because the search for the builder is performed on the whole field, the extra line causes the error message "The specified builder was not found." References "Foxtalk", February 1995, "An Introduction to Visual FoxPro's Builders", p. 23, Ken Levy. Microsoft Developer's Network (MSDN),.July 1995, "Wizards and Builders in Microsoft FoxPro", David T. Anderson Microsoft Product Support Services