Connecting shapes using GlueTo

Started by charlykuntz, July 20, 2012, 02:43:41 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

charlykuntz

Hello everybody,

I'm into troubles that nearly drive my crazy. I would like to achieve connections between shapes by using GlueTo which ends in a COMException. Before I get close to the error I want to explain what happens before:

1. Load 500 shapes from the stencil into an shape array:
Code (C#) Select
shapes[index] = stencil.Masters[@"SHAPENAME"].Shapes[1];
Everything works fine here.

2. Load 499 connector shapes from the into the shape array:
Code (C#) Select
shapes[index] = stencil.Masters[@"CONNECTORNAME"].Shapes[1]
Still everthing's fine.

3. Make some property changes to the 2-D-shapes and drop all 999 shapes:
Code (C#) Select
page.Drop(shapes[index], X-VALUE, Y-VALUE);

4. Glue the connector's BeginX to a shape's PinX:
Code (C#) Select
Cell conBeginX = shapes[index].CellsSRC[(short) VisSectionIndices.visSectionObject, (short) VisRowIndices.visRowXForm1D, (short) VisCellIndices.vis1DBeginX];
conBeginX.GlueTo(fromShape.CellsSRC[(short) VisSectionIndices.visSectionObject, (short) VisRowIndices.visRowXFormOut, (short) VisCellIndices.visXFormPinX]);


I get the COMException at the last line with the message: "Inappropriate target object for this action"

I also used AutoConnect which failed at the same level but worked while I dropped the shapes directly out of the master instead of dropping them out of the shape array (could there be the problem?).

I'll be glad for every kind of advice.

Have a nice weekend.

Charly.

Jumpy

You can't glue to the PinX cell. You normally glue to a ConnectionPoint. I guess you wan't to achieve dynamic glueing? That is done in a different way, that I (sorry) can't remember at the momnet, but perhaps you can look arround a bit or one of the other guys, knows how to.

hth Jumpy

charlykuntz

Hi Jumpy,

thanks for your advice. I also tried to glue the connector's BeginX to a other shape's connection point which failed too because of an "Inappropriate target object for this action". Even the shape.AutoConnect function delivers the same error. My mistake seems to be somewhere else. Maybe it is not possible to glue shapes that are not directly derived from a master?

charly.

aledlund

This works for me. I included a couple of functions to create some 'standard' connection points as examples.




        Dim strNodeAConn As String
        Dim strNodeBConn As String
' strPortA and strPortB are the connection point names (ex. center, left, right, top, bottom)
        strNodeAConn = "Connections." & strPortA
        strNodeBConn = "Connections." & strPortB
' strNodeA and strNodeB are obviously the shapenames
        Set objNodeA = vsoShapes.Item(strNodeA)
        Set objNodeB = vsoShapes.Item(strNodeB)

' objCable is the dynamic connector
        Dim objBeginX As Visio.Cell
        Dim objEndX As Visio.Cell
        Set objBeginX = objCable.CellsSRC( _
                visSectionObject, visRowXForm1D, vis1DBeginX)
        objBeginX.GlueTo objNodeA.Cells(strNodeAConn)
        Set objEndX = objCable.CellsSRC( _
            visSectionObject, visRowXForm1D, vis1DEndX)
        objEndX.GlueTo objNodeB.Cells(strNodeBConn)
        DoEvents




    '*********************************************************************
    '*********************************************************************
    '
    '       Standard Connections (left, right, top, bottom, center)
    '
    '*********************************************************************
    '*********************************************************************

    Public Sub AddStandardConnections _
            (ByVal visShape As Visio.Shape)

        Dim visSection As Integer
        Dim blnResult As Boolean

            visSection = visSectionConnectionPts
            ' check to make sure the section exists first
            If visShape.SectionExists(visSection, False) = False Then
                visShape.AddSection (visSection)
            End If

            ' since we have connections on all four sides we probably dont need a middle
             blnResult = funcAddConnectionPointToShape(visShape, "center", "center", "center", _
                   2, "Width * 0.5", "Height * 0.5", 0, False)

            blnResult = AddConnectionPointToShape(visShape, "left", "left", "left", _
            2, "0", "Height * 0.5", "0", False)

            blnResult = AddConnectionPointToShape(visShape, "right", "right", "right", _
            2, "Width", "Height * 0.5", "0", False)

            blnResult = AddConnectionPointToShape(visShape, "top", "top", "top", _
            2, "Width * 0.5", "Height", "0", False)

            blnResult = AddConnectionPointToShape(visShape, "bottom", "bottom", "bottom", _
            2, "Width * 0.5", "0", "0", False)


    End Sub

    '*********************************************************************
    '*********************************************************************
    '
    '               Connection Points
    '
    '*********************************************************************
    '*********************************************************************

    Public Function AddConnectionPointToShape _
                    (ByVal vsoShape As Visio.Shape, _
                    ByVal strLocalRowName As String, _
                    ByVal strRowNameU As String, _
                    ByVal strLabelName As String, _
                    ByVal strConnectType As String, _
                    ByVal strX As String, _
                    ByVal strY As String, _
                    Optional ByVal strDirX As String = "", _
                    Optional ByVal strDirY As String = "", _
                    Optional ByVal blnAutoGen As Boolean = False) _
                    As Boolean

        Dim vsoCell As Visio.Cell
        Dim intRowIndex As Integer

            If vsoShape.SectionExists(visSectionConnectionPts, False) = False Then
                vsoShape.AddSection (visSectionConnectionPts)
            End If

            intRowIndex = vsoShape.AddNamedRow(visSectionConnectionPts, _
                 strLocalRowName, _
                 Visio.VisRowIndices.visRowConnectionPts)

            ' Column 0: X
            Set vsoCell = vsoShape.CellsSRC(visSectionConnectionPts, _
                visRowConnectionPts + intRowIndex, visX)
            vsoCell.Formula = strX

            If (strLocalRowName <> strRowNameU And _
                Len(strRowNameU) > 0) Then
                vsoCell.RowNameU = strRowNameU
            End If

            ' Column 1: Y
            Set vsoCell = vsoShape.CellsSRC(visSectionConnectionPts, _
                visRowConnectionPts + intRowIndex, visY)
            vsoCell.Formula = strY

            ' Column 2: direction x
            Set vsoCell = vsoShape.CellsSRC(visSectionConnectionPts, _
                visRowConnectionPts + intRowIndex, visCnnctDirX)
            vsoCell.Formula = strDirX

            ' Column 3: direction y
            Set vsoCell = vsoShape.CellsSRC(visSectionConnectionPts, _
                visRowConnectionPts + intRowIndex, visCnnctDirY)
            vsoCell.Formula = strDirY

            ' Column 4: type
            Set vsoCell = vsoShape.CellsSRC(visSectionConnectionPts, _
                visRowConnectionPts + intRowIndex, visCnnctType)
            vsoCell.Formula = strConnectType

            ' Column 5: autogen
            Set vsoCell = vsoShape.CellsSRC(visSectionConnectionPts, _
                visRowConnectionPts + intRowIndex, visCnnctAutoGen)
            vsoCell.ResultIU = blnAutoGen

            AddConnectionPointToShape = True


    End Function


charlykuntz

@alelund:

Where do you get the vsoShapes from?

aledlund

sorry (my fault for trying to just grab what was relevant).
dim vsoShapes as visio.shapes
set vsoShapes = application.activepage.shapes

al

charlykuntz

Hi aledlund,

thank you for your explanation. I think my question wasn't as precise as it had to be.

There is no problem when I drop the shapes calling
Code (C#) Select
page.Drop(stencil.Masters["MASTERNAME"], X, Y) In this case GlueTo works without any error. But when I add the shapes to an array shapes[index] = stencil.Masters[@"SHAPENAME"].Shapes[1]; and drop them later page.Drop(shapes[index], X-VALUE, Y-VALUE); GlueTo fails as well as shape.AutoConnect.

aledlund

If it's always on the last shape in the array, I start to suspect an indexing issue (start at 0 vs start at 1, or vicea-versa).
al

charlykuntz

Unfortunately it's already the first item of the which connection does not work. But these one based indices of Visio elements are nevertheless very awful.

Jumpy

The dropping of the Array of shapes is still OK I guess?

So could you perhaps post a little more code. Everything arround the part, where you attempt the glueing (perhaps including the loop(s)).

charlykuntz

Ok. So here is (almost) the whole code:

ActiveDiagramControl: the Visio OCX


if (ActiveDiagramControl.Instance != null)
            {
                Application visioApplication = ActiveDiagramControl.Instance.Document.Application;
                Page page = visioApplication.ActivePage;
                Document stencil = visioApplication.Documents[2];
                Document drawing = visioApplication.ActiveDocument;
                Shape[] shapes = new Shape[graphicElements.Count];
                int index = 0;
               
                // Create the shapes
                foreach(GraphicElement element in graphicElements)
                {
                    switch (element.ElementType)
                    {
                            case ElementType.Function:
                            {
                                shapes[index] = stencil.Masters["Function"].Shapes[1];
                                break;
                            }
                            case ElementType.Connector:
                            {
                                shapes[index] = stencil.Masters["Connector"].Shapes[1];
                                break;
                            }
                    }
                    index++;
                }
               
                visioApplication.ShowChanges = false;
                             
                index = 0;
                bool isFunctionDropped = false;
                bool isConnectorDropped = false;
                string lastFunctionName = string.Empty;
                string lastConnectorName = string.Empty;

                foreach(GraphicElement element in graphicElements)
                {
                    if (shape.OneD == 0)
                    {
                        shapes[index].Text = index.ToString();
                        shapes[index].Cells["Width"].Formula = "30mm";
                        shapes[index].Cells["Height"].Formula = "20mm";
                        shapes[index].Cells["LineWeight"].Formula = "1mm";
                        shapes[index].Cells["LineColor"].Formula = "1";
                        shapes[index].Cells["Rounding"].Formula = "0.3mm";
                        shapes[index].Cells["FillBkgnd"].Formula = "2";
                        shapes[index].Cells["FillForegndTrans"].Formula = "90%";
                        shapes[index].Cells["FillBkgndTrans"].Formula = "0%";
                        shapes[index].Cells["FillForegnd"].Formula = "3";
                       
                        lastFunctionName = shape.Name;
                        isFunctionDropped = true;
                        if (isConnectorDropped)
                        {
                            Cell conEndX = page.Shapes[lastConnectorName].CellsSRC[VisEnum.VIS_SECTION_OBJECT, VisEnum.VIS_ROWX_FORM_1_D, VisEnum.VIS_1_D_END_X];
                            conEndX.GlueTo(shape.Cells["Connections.W"]);
                        }
                       
                    }
                   
                    page.Drop(shapes[index], element.X, element.Y);

                    // Glue
                    if (shape.OneD == -1 && index > 0 && isFunctionDropped)
                    {
                        // Connector's begin to
                        Shape fromShape = page.Shapes[lastFunctionName];
                        Cell conBeginX = shapes[index].CellsSRC[VisEnum.VIS_SECTION_OBJECT, VisEnum.VIS_ROWX_FORM_1_D, VisEnum.VIS_1_D_BEGIN_X];
                        conBeginX.GlueTo(fromShape.Cells["Connections.E"]);
                        lastConnectorName = shape.Name;
                        isConnectorDropped = true;
                    }
                    index++;
                }



I made minor modifications to my code so I hope it is consistent yet.

Jumpy

In the second ForEach-Loop, the first time the variable shape is not defined or is not assigned.
Later on, when you drop the shape:

page.Drop(shapes[index], element.X, element.Y);

you don't retain a reference to that shape.

With sth. like:

Shape Newshape = page.Drop(shapes[index], element.X, element.Y);

you can maybe avoid the complications with remembering the last shape via it's name:

Shape fromShape = page.Shapes[lastFunctionName];


--------------

If the shapes are alternating, e.g. function connector function connector function ...
you could try a different aproach by simply use of two variables, oldshape, newshape:

If newshape is a function and oldshape is empty, do nothing because it's the first shape (ecxept the Alterations of some properties)
If newshape is a function and oldshape is/has to be a connecor then glue the end of the connector to newshape
(and make the Alterations of some properties)
If newshape is a connector and oldshape is/has to be a function then glue begin of the connector to oldshape
Finally set Oldshape=newshape
Loop

charlykuntz

Hi Jumpy,

thank you very much for this advice. I tried it with only one connection an it worked as demanded. Now I am going try it with thousand shapes but I got no doubts it will work too.