Share via


Optimizing Forms and Controls

You can make significant improvements to the forms and controls in your application by optimizing their performance.

For example, by using a data environment for a form or report, opening tables can be 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.

Note

If you do use a form set, you will gain some performance 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.

The following steps outline how to dynamically load page controls:

  1. Design your form as usual 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 as a class.

  3. Open the class you created to make sure 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 reduce the load time for a form that contains many data-bound controls if you delay the binding of those controls until needed.

The following steps describe the process for binding controls to data dynamically:

  1. Put the tables and views for your form in the data environment so that they open when the form loads.

  2. For each bound control, add code to its GotFocus event code that binds the control to the data value when the control receives focus.

    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, to 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, suppose that you want to make controls visible or invisible, change control colors, or move records in bound controls. It is recommended that you delay painting those controls until after completing changes to controls.

The following steps outline the process for delaying screen refresh:

  1. Set the form's LockScreen property to True (.T.).

  2. Update the controls as required.

  3. Call the form's Refresh method.

  4. Set the form's LockScreen property to False (.T.).

Tip

This technique does not provide an increase in performance when updating single controls.

For example, the following code 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 is not set to True, each of these operations repaint the affected controls individually and reduces performance of the update operation:

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.

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

Concepts

Using Rushmore Query Optimization to Speed Data Access

Other Resources

Optimizing Applications

Optimizing Your System