Placing Shapes in a Drawing

Determining where to place shapes can be one of the more challenging tasks for a program that creates Microsoft® Visio® drawings, especially in connected diagrams or other kinds of drawings with complex relationships between shapes. The ultimate goal is the same: You'll need to calculate a pair of page coordinates for each shape you place on the drawing page. The approach you take will depend on the kind of drawing you're trying to create and the data on which the drawing is based.

In addition, Visio provides automatic layout capabilities that control how the shapes and connectors between shapes in your drawing interact. You can view the default layout settings in the Page Layout and Shape Layout sections in a ShapeSheet® window. You can customize these settings in your program by working with the formulas in these sections. For details about shapes and automatic layout, see Designing Shapes for Automatic Layout in Chapter 11, Arranging Shapes in Drawings. For details about the Page Layout and Shape Layout sections, see the Microsoft Visio Developer Reference (on the Help menu, click Developer Reference).

In this section…

Placing Shapes Using Automation: an Example

Placing Shapes in Relation to Other Shapes

Placing Shapes Using Automation: an Example

The following CreateDrawing procedure provides an example of placing shapes in a simple network diagram. The example reads data from a two-dimensional array—the first element in the array describes the name of a master in the Basic Network Shapes 3D stencil, and the second element of the array is a shape label. CreateDrawing places a hub in the middle of the page, and then places the components in a circle around the hub.

This example demonstrates several techniques for placing shapes, including the following:

  • To place the hub in the middle of the page, the program uses the values in the PageHeight and PageWidth cells of the page sheet.
  • To place shapes evenly around the hub, the variable dblDegreeInc was calculated based on the number of elements in the array. This variable was then used to identify the x- and y-coordinates for dropping the shape.

Public Sub CreateDrawing(arrNetData As String)     Dim shpObjHUB As Visio.Shape     Dim shpObjNodes As Visio.Shape     Dim mstObj As Visio.Master     Dim stnObj As Visio.Document     Dim dblX, dblY As Double     Dim dblDegreeInc As Double     Dim dblRad As Double     Dim dblPageWidth, dblPageHeight As Double     Dim i As Integer     Const PI = 3.1415     Const CircleRadius = 2     'Divide the circle by the number of objects in the array so they are spaced evenly     dblDegreeInc = 360 / UBound(arrNetData)     'Read the PageWidth and PageHeight properties     dblPageWidth = ActivePage.PageSheet.Cells("PageWidth").ResultIU     dblPageHeight = ActivePage.PageSheet.Cells("PageHeight").ResultIU     'Open the Basic Network Shapes 3D stencil     Set stnObj = Application.Documents.OpenEx("Basic Network Shapes 3D.vss", visOpenDocked)     'Process the hub shape     Set mstObj = stnObj.Masters(arrNetData(0, 0))     Set shpObjHUB = ActivePage.Drop(mstObj, dblPageWidth / 2, dblPageHeight / 2)     'Set the text of the hub shape     shpObjHUB.Text = arrNetData(0, 1)     'Process the nodes     For i = 1 To UBound(arrNetData)         Set mstObj = stnObj.Masters(arrNetData(i, 0))         'Determine X, Y location for placement (in circle around hub)         dblRad = (dblDegreeInc * i) * PI / 180         dblX = CircleRadius * Cos(dblRad) + (dblPageWidth / 2)         dblY = CircleRadius * Sin(dblRad) + (dblPageHeight / 2)         'Add shape to drawing in proper location         Set shpobj = ActivePage.Drop(mstObj, dblX, dblY)         'Set shape text         shpobj.Text = arrNetData(i, 1)     Next End Sub

Notice the use of page sheet properties to get information about positioning on the page. Shapes are spaced evenly around the hub by using the dblDegreeInc variable to calculate the x- and y-coordinates based on the number of elements in the array.

Note To calculate page coordinates that are visible in the drawing window, use the GetViewRect method of a Window object. You can use these coordinates to place shapes in the middle of a window. For details, see the GetViewRect method in the Microsoft Visio Developer Reference (on the Help menu, click Developer Reference).

TOP

Placing Shapes in Relation to Other Shapes

If you want to find shapes based on whether they are located on or near other shapes, or modify a shape's behavior relative to another shape, you can use these properties: SpatialRelation, SpatialNeighbors, SpatialSearch, DistanceFrom, DistanceFromPoint, and HitTest.

You can use these properties to create shapes that change their settings based on the other shapes they are dropped on or near. For example, in an office layout solution, you could create smart furniture shapes such as a cabinet shape that attaches itself to a wall when dropped next to it, and takes on the style of a cabinet that is located nearby. Or, you can prevent a user from placing a shape near or on certain other shapes, such as not allowing a user to drop a fire extinguisher near any type of heat source in a building layout.

Properties or methods that determine spatial relationships between shapes

Property or method

Description

SpatialRelation property

Returns an integer that represents the spatial relationship of one shape to another shape. Both shapes must be on the same page or in the same master.

Use this property to determine whether one shape contains, is contained by, overlaps, or touches another shape.

SpatialNeighbors property

Returns a Selection object that represents the shapes that meet certain criteria in relation to a specified shape.

Use this property to find a set of shapes that contain, are contained by, overlap, or touch a specific shape.

SpatialSearch property

Returns a Selection object whose shapes meet certain relationship criteria in relation to a point that is expressed in the coordinate space of a page, master, or group.

Use this property to find a set of shapes that contain, are contained by, overlap, or touch a specific coordinate space.

DistanceFrom property

Returns the distance from one shape to another. Both shapes must be on the same page or in the same master.

Use this property to determine if one shape is within a required distance of another shape.

DistanceFromPoint property

Returns the distance from a shape to a point.

Use this property to determine if a coordinate on a shape is within a required distance of a point.

HitTest property

Determines if a given x,y position hits outside, inside, or on the boundary of a shape.

Use this property to check one shape against criteria for a limited set of other shapes.

Using the SpatialRelation property: an example

The SpatialRelation property of a Shape object returns the relationship between the calling shape and another shape (passed as an argument with the property).

The Microsoft® Visual Basic® for Applications (VBA) code in the following example assumes the user can drop any shape from the document stencil onto a page with existing shapes. The text of each shape on the page changes to display the relationship between the dropped shape and each shape in the drawing.

Private Sub Document_ShapeAdded(ByVal Shape As IVShape)     Dim ShapeOnPage As Shape     Dim dblTolerance As Integer     Dim iSpatialRelation As VisSpatialRelationCodes     Dim strSpatialRelation As String

    On Error GoTo errHandler

    'Try setting different tolerance values     dblTolerance = 0.25

    For Each ShapeOnPage In ActivePage.Shapes         If Shape = ShapeOnPage Then             'The shape being tested is the shape that was added             'Display the shape name             Shape.Text = Shape.Name         ElseIf ShapeOnPage.Name <> "Abstract" Then             'Get the relation between the added shape, and the             'iterated shape on the page             iSpatialRelation = Shape.SpatialRelation(ShapeOnPage, _                 dblTolerance, 0)             'Convert return code to text             Select Case iSpatialRelation                 Case VisSpatialRelationCodes.visSpatialContain                     strSpatialRelation = "Contains"                 Case VisSpatialRelationCodes.visSpatialContainedIn                     strSpatialRelation = "is Contained in"                 Case VisSpatialRelationCodes.visSpatialOverlap                     strSpatialRelation = "overlaps"                 Case VisSpatialRelationCodes.visSpatialTouching                     strSpatialRelation = "is touching"                 Case Else                     strSpatialRelation = "has no relation with"             End Select             'Put relation on shape             ShapeOnPage.Text = Shape.Name & " " & strSpatialRelation & _                 " " & ShapeOnPage.Name         End If     Next     errHandler:

End Sub

Using the SpatialNeighbors property: an example

You can use the SpatialNeighbors property of a Shape object in your program to determine the relationship between the shape of interest and the rest of the shapes on the page. The property returns the set of shapes (as a Selection object) that meet the criteria set by the arguments passed with the property. For details about using the Selection object, see Working with Selected Shapes later in this chapter.

The VBA code in this example assumes the user will drop a shape within the boundaries of a square, circle, or both, already provided on the drawing page. The text of the dropped shape displays the results of the property being called.

Private Sub Document_ShapeAdded(ByVal Shape As IVShape)     Dim ShapeOnPage As Shape     Dim dblTolerance As Integer     Dim ReturnedSelection As Selection     Dim strSpatialRelation As String     Dim iSpatialRelation As VisSpatialRelationCodes

    On Error GoTo errHandler

    strSpatialRelation = ""

    'Try setting different tolerance values     dblTolerance = 0#

    'Try setting different spatial relationships     iSpatialRelation = visSpatialContainedIn

    Const ISRELATED = " is contained by "     Const ISNOTRELATED = " is not contained."

    'Get the set of spatially related shapes     'that meet the criteria set by the parameters     Set ReturnedSelection = Shape.SpatialNeighbors(iSpatialRelation, _         dblTolerance, 0)

    'Evaluate the results     If ReturnedSelection.Count = 0 Then         'No shapes met the criteria set by the         'parameters of the method         strSpatialRelation = Shape.Name & ISNOTRELATED     Else         'Build the positive result string         For Each ShapeOnPage In ReturnedSelection             strSpatialRelation = strSpatialRelation & Shape.Name _                 & ISRELATED & ShapeOnPage.Name & Chr$(10)         Next     End If

    'Put the results on the added shape     Shape.Text = strSpatialRelation

    errHandler:

End Sub

Using the DistanceFrom and DistanceFromPoint properties: an example

The VBA code in this example demonstrates the DistanceFrom and DistanceFromPoint properties of a Shape object. These properties are used to determine the distance from the calling shape, and a shape passed as an argument with the property. Use DistanceFromPoint to determine the distance from a specific point on the shape.

The VBA code in this example expects the user to drop various shapes onto the page at various distances from a base shape. A message box appears to inform the user if the dropped shapes are too close to the base shape. The minimum acceptable distance is defined by dblMinimumDistance.

To test this example, paste the following code in the ThisDocument code window of a new drawing, save the drawing and close it, reopen the drawing, and then drop shapes onto the page.

Public objBaseShape As Visio.Shape

Public Function MeetsClearanceRequirements(BaseShape As Shape, _         ShapeToCheck As Shape, dblMinimumDistance As Double) As Boolean     Dim bRetVal As Boolean     On Error GoTo errHandler     'Check distance from specific point     'Use the DistanceFromPoint property     dblDistance = ShapeToCheck.DistanceFromPoint(BaseShape.Cells("PinX"), _         BaseShape.Cells("PinY"), 0)     'To check distance from closest points use DistanceFrom property:     'dblDistance = ShapeToCheck.DistanceFrom(BaseShape,0)     If dblDistance < dblMinimumDistance Then         bRetVal = False     Else         bRetVal = True     End If     MeetsClearanceRequirements = bRetVal     Exit Function

    errHandler:         bRetVal = False End Function

Private Sub Document_DocumentOpened(ByVal doc As IVDocument)     'Draw a rectangle on the page; this will be the     'shape that all added shapes are compared to     Set objBaseShape = ActivePage.DrawRectangle(3, 7, 4, 6) End Sub

Private Sub Document_ShapeAdded(ByVal Shape As IVShape)     Dim strMsg As String     Dim dblMinimumDistance As Double

dblMinimumDistance = 2

'Because the objBaseShape is set when the document is opened,     'attempt to compare shapes on different pages     If objBaseShape.Parent = Shape.Parent And (objBaseShape <> Shape) Then         If MeetsClearanceRequirements(objBaseShape, Shape, _             dblMinimumDistance) Then             strMsg = "Distance requirements met"         Else             strMsg = "Too close"         End If         'Display message         MsgBox strMsg     Else         'Do nothing, shapes are on a different page, or         'BaseShape = Added Shape     End If End Sub