Builders

Builders are utility programs that work on objects in the Form and Class Designers. They can be anything from a simple property manipulators to complex object setup utilities.

 

07-Jun-04 Click here for the Europa Anchor builder

Here is the simplest general purpose builder:

* mybuild.prg

lparameter lcCommand

local i, n, laObjects[1]

lcCommand = "laObjects[i]." + lcCommand

n = aselobj( laObjects ) && all selected objects
for i = 1 to n
   &lcCommand
endfor

To use it select the objects you want to manipulate and in the command window do something like:

mybuild( "FontName = [Arial]" ) set the font of all the objects to Arial
mybuild( "ForeColor = 255" ) set the objects to red

Here's a builder that was needed in VFP3 to horizontally center more that one controls. In VFP5 the layout toolbar now provides this functionality. To use this builder select the controls to center and in the command window type: hcenter()

* hcenter.prg 21-Oct-96

* Usage: select object(s) to be horizontally centered within their container
* in the command window enter =hcenter()

* Copyright 1996, DF Software Development, Inc.

local n, laObjects[1]

n = aselobj( laObjects )  && all selected objects
if ( n = 0 )
   * nothing to do
   wait window "Select one or more controls to center horizontally" nowait
   return
endif

local i, loParent, lnMinX, lnMaxX, lnAdjustX

* find the container object
loParent = laObjects[1].Parent
if ( loParent.BaseClass == "Page" )
   * if it's a page go on up to the pageframe
   loParent = loParent.Parent
endif

* determine the X limits of the selected objects
lnMinX = 999999
lnMaxX = -999999
for i = 1 to n
   with laObjects[i]
      lnMinX = min( lnMinX, .Left )
      lnMaxX = max( lnMaxX, .Left + .Width )
   endwith
endfor

* number of X pixels to shift each object
if ( loParent.BaseClass == "Pageframe" )
   lnAdjustX = lnMinX - ( loParent.PageWidth - ( lnMaxX - lnMinX ) ) / 2
else
   lnAdjustX = lnMinX - ( loParent.Width - ( lnMaxX - lnMinX ) ) / 2
endif

* move each object
for i = 1 to n
   with laObjects[i]
      .Left = .Left - lnAdjustX
   endwith
endfor

 

The parallel builder for vertical centering:

* vcenter.prg 21-Oct-96

* Usage: select object(s) to be vertically centered within their container
* in the command window enter =vcenter()

* Copyright 1996, DF Software Development, Inc.

local n, laObjects[1]

n = aselobj( laObjects )  && all selected objects
if ( n = 0 )
   * nothing to do
   wait window "Select one or more controls to center vertically" nowait
   return
endif

local i, loParent, lnMinY, lnMaxY, lnAdjustY

* find the container object
loParent = laObjects[1].Parent
if ( loParent.BaseClass == "Page" )
   * if it's a page go on up to the pageframe
   loParent = loParent.Parent
endif

* determine the Y limits of the selected objects
lnMinY = 999999
lnMaxY = -999999
for i = 1 to n
   with laObjects[i]
      lnMinY = min( lnMinY, .Top )
      lnMaxY = max( lnMaxY, .Top + .Height )
   endwith
endfor

* number of Y pixels to shift each object
if ( loParent.BaseClass == "Pageframe" )
   lnAdjustY = lnMinY - ( loParent.PageHeight - ( lnMaxY - lnMinY ) ) / 2
else
   lnAdjustY = lnMinY - ( loParent.Height - ( lnMaxY - lnMinY ) ) / 2
endif

* move each object
for i = 1 to n
   with laObjects[i]
      .Top = .Top - lnAdjustY
   endwith
endfor

 


New Updated 15-Aug-97

Here are two builders that provide a nice feature still missing from the VFP5 and VFP3 layout toolbars. The VFP5 designer Format menu includes a Horizontal/Vertical Spacing item but it works slightly different that the functions here. These builders take a group of 3 or more controls and equispace them horizontally or vertically by distributing the controls within the space limits assigned to the controls. That is they put the same amount of space between the controls. To use these builders put one control at the left (top) edge of the area, put the last control at the right (bottom) edge, select all the controls to position and in the command window type: hequispace() or vequispace(). The code looks a lot like the above code for hcenter().

* hequispace.prg 15-Aug-97

* Usage: select object(s) to be horizontally equispaced within their limits
* in the command window enter =hequispace()

* Copyright 1997, DF Software Development, Inc.

PARAMETERS uP1, uP2, uP3 && builders get sent 3 parameters by builder.app

local n, laObjects[1]

n = aselobj( laObjects )  && all selected objects
if ( n < 3 )
   * nothing to do
   wait window "Select three or more controls to horizontally equispace" nowait
   return
endif

local i, lnMinX, lnMaxX, lnAdjustX, lnTotalWidth

* determine the X limits of the selected objects

lnMinX = 999999
lnMaxX = -999999
lnTotalWidth = 0
for i = 1 to n
   with laObjects[i]
      lnMinX = min( lnMinX, .Left )
      lnMaxX = max( lnMaxX, .Left + .Width )
      lnTotalWidth = lnTotalWidth + .Width
   endwith
endfor

* number of X pixels between each object

lnAdjustX = ( lnMaxX - lnMinX - lnTotalWidth ) / ( n - 1 )

* move objects 2..n-1

for i = 2 to n - 1
   with laObjects[i]
      .Left = laObjects[i-1].Left + laObjects[i-1].Width + lnAdjustX
   endwith
endfor

 

And the parallel vequispace:

* vequispace.prg 15-Aug-97

* Usage: select object(s) to be vertically equispaced within their limits
* in the command window enter =vequispace()

* Copyright 1997, DF Software Development, Inc.

PARAMETERS uP1, uP2, uP3 && builders get sent 3 parameters by builder.app

local n, laObjects[1]

n = aselobj( laObjects )  && all selected objects
if ( n < 3 )
   * nothing to do
   wait window "Select three or more controls to vertically equispace" nowait
   return
endif

local i, lnMinY, lnMaxY, lnAdjustY, lnTotalHeight

* determine the Y limits of the selected objects

lnMinY = 999999
lnMaxY = -999999
lnTotalHeight = 0
for i = 1 to n
   with laObjects[i]
      lnMinY = min( lnMinY, .Top )
      lnMaxY = max( lnMaxY, .Top + .Height )
      lnTotalHeight = lnTotalHeight + .Height
   endwith
endfor

* number of Y pixels between each object

lnAdjustY = ( lnMaxY - lnMinY - lnTotalHeight ) / ( n - 1 )

* move objects 2..n-1

for i = 2 to n - 1
   with laObjects[i]
      .Top = laObjects[i-1].Top + laObjects[i-1].Height + lnAdjustY
   endwith
endfor

Maybe you noticed the PARAMETERS statement in the builders, but the parms are not used anywhere. The reason for this is because these builders can be attached to the VFP BUILDER.APP program that is called when you select Builder... from the context menu in the Form/Class designer. The open architecture of the VFP builder allows our own builders to be easily added to the system. All that needs to be done is to "register" the builders in the \WIZARDS\BUILDER.DBF. Here's how to do this from the command window:

use home()+"wizards\builder.dbf"
insert into builder values ("Horizontal Equispacer", ;
   "Put the same amount of horizontal space between selected objects", ;
   "", "MULTISELECT", "hequispace.prg", "", "", "" )

insert into builder values ("Vertical Equispacer", ;
   "Put the same amount of vertical space between selected objects", ;
   "", "MULTISELECT", "vequispace.prg", "", "", "" )
use

The value MULTISELECT means that these builders are only to be used when more than one object is selected. Although these builders require 3 or more objects are selected. Now when you select the controls you can access these builders via the context menu instead of using the command window.

Here's a couple of relevant KB Articles Q138979, Q141797 and Q147787

1