Optimizing Forms and Controls

You can also make significant improvements in the forms and controls in your application.

Using the Data Environment

If you use the data environment of the Form Designer or Report Designer, table open performance is much faster than executing USE, SET ORDER, and SET RELATION commands in the form Load event. When you use the data environment, Visual FoxPro uses low-level engine calls to open the tables and set up the indexes and relations.

Limiting the Number of Forms in a Form Set

Use form sets only when it is necessary to have a group of forms share a private data session. When you use a form set, Visual FoxPro creates instances of all forms and all controls on all forms in the form set, even though the first form in the form set is the only one being displayed. This can be time consuming, and is unnecessary if the forms don't have to share a private data session. Instead, you should execute DO FORM for other forms when they're needed.

However, if you do use a form set, you will gain some performance back when you access the forms in the form set, because the forms will already be loaded but not visible.

Dynamically Loading Page Controls on a Page Frame

Page frames, like form sets, load all the controls for each page when the page frame is loaded, which can cause a noticeable delay when the page frame is loaded. Instead, you can dynamically load page controls, as needed, by creating a class out of the controls on each page, then loading them as the page is activated.

To dynamically load page controls

  1. Design your form as you normally would, including all controls on all pages.

  2. When your design is complete, go to the second page of your page frame, and save the controls you find there as a class.

  3. Open the class you created, and ensure the controls are still properly laid out.

  4. Repeat Steps 2 and 3 for the third and subsequent pages of the page frame.

  5. In the Activate event of the second and subsequent pages of the page frame, add objects and make them visible.

    For example, if your controls class is named cnrpage1, you would add the following code:

    IF THIS.ControlCount = 0
       THIS.AddObject("cnrpage1","cnrpage1")
       THIS.cnrpage1.Visible = .T.
    ENDIF
    

Dynamically Binding Controls to Data

You can speed the load time for a form that contains many data-bound controls if you delay the binding of those controls until they're needed.

To dynamically bind controls to data

  1. Put the tables and views for your form in the data environment so that they're opened when the form is loaded.

  2. For each bound control, add code to its GotFocus event code that binds the control to the data value. For example, the following code binds a ComboBox control to the customer.company field:

    * Check to see if the control has been bound yet.
    IF THIS.RecordSource = ""
       * Set the record source to the right value
       * and set the record source type to "fields"
       THIS.RecordSource = "customer.company"
       THIS.RecordSourceType = 6
       THIS.Refresh
    ENDIF
    

Delaying Screen Refresh

If you must make several changes to the screen — for example, change the values of several controls at once — you can reduce the overall time required to update the screen by delaying screen refresh until all changes are done. For example, if you make controls visible or invisible, change control colors, or move records in bound controls, it is much more efficient to delay the painting of those controls until after the changes have all been completed:

To delay screen refresh

  1. Set the form's LockScreen property to true.
  2. Update the controls as required.
  3. Call the form's Refresh method.
  4. Set the form's LockScreen property to false.

For example, the following example changes the display properties of several properties at once, moves to a new record, and only then refreshes the screen with new information. If LockScreen were not set to true, each of these operations would repaint the affected controls individually and the overall update performance would seem sluggish.

THISFORM.LockScreen = .T.
THISFORM.MyButton.Caption = "Save"
THISFORM.MyGrid.BackColor = RGB (255, 0, 0) && Red
SKIP IN customers
SKIP IN orders
THISFORM.Refresh
THISFORM.LockScreen = .F.

Tip   This technique doesn't provide any benefit if you're updating only a single control.

Reducing Code in Frequently-Used Methods

Because the Refresh method and Paint event are called frequently, you can improve performance in forms by reducing the amount of code in these methods. Similarly, to speed the load time for a form, you could move code from the Init event to a less frequently used event such as Activate, Click, and GotFocus. Then, you use a property on the control (such as Tag or a custom property) to keep track of whether the control has already run code that only needs to be run once.

See Also

Using RushmoreQuery Optimization to Speed Data Access | Optimization of Programs | Optimizing Applications | Optimizing Your System