Author Topic: Connecting shapes using GlueTo  (Read 8034 times)

0 Members and 1 Guest are viewing this topic.

charlykuntz

  • Full Member
  • ***
  • Posts: 76
Connecting shapes using GlueTo
« on: July 20, 2012, 09:43:41 AM »
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

  • Hero Member
  • *****
  • Posts: 1061
Re: Connecting shapes using GlueTo
« Reply #1 on: July 23, 2012, 02:01:36 AM »
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

  • Full Member
  • ***
  • Posts: 76
Re: Connecting shapes using GlueTo
« Reply #2 on: July 23, 2012, 02:57:58 AM »
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

  • Hero Member
  • *****
  • Posts: 1412
Re: Connecting shapes using GlueTo
« Reply #3 on: July 23, 2012, 07:15:51 AM »
This works for me. I included a couple of functions to create some 'standard' connection points as examples.

Code: [Select]


        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

  • Full Member
  • ***
  • Posts: 76
Re: Connecting shapes using GlueTo
« Reply #4 on: July 23, 2012, 09:40:42 AM »
@alelund:

Where do you get the vsoShapes from?

aledlund

  • Hero Member
  • *****
  • Posts: 1412
Re: Connecting shapes using GlueTo
« Reply #5 on: July 23, 2012, 10:59:47 AM »
sorry (my fault for trying to just grab what was relevant).
dim vsoShapes as visio.shapes
set vsoShapes = application.activepage.shapes

al

charlykuntz

  • Full Member
  • ***
  • Posts: 76
Re: Connecting shapes using GlueTo
« Reply #6 on: July 24, 2012, 07:36:34 AM »
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
Code: [Select]
shapes[index] = stencil.Masters[@"SHAPENAME"].Shapes[1]; and drop them later
Code: [Select]
page.Drop(shapes[index], X-VALUE, Y-VALUE); GlueTo fails as well as shape.AutoConnect.

aledlund

  • Hero Member
  • *****
  • Posts: 1412
Re: Connecting shapes using GlueTo
« Reply #7 on: July 24, 2012, 11:47:54 AM »
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

  • Full Member
  • ***
  • Posts: 76
Re: Connecting shapes using GlueTo
« Reply #8 on: July 25, 2012, 02:46:07 AM »
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

  • Hero Member
  • *****
  • Posts: 1061
Re: Connecting shapes using GlueTo
« Reply #9 on: July 25, 2012, 04:53:29 AM »
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

  • Full Member
  • ***
  • Posts: 76
Re: Connecting shapes using GlueTo
« Reply #10 on: July 25, 2012, 08:36:33 AM »
Ok. So here is (almost) the whole code:

ActiveDiagramControl: the Visio OCX


Code: [Select]
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

  • Hero Member
  • *****
  • Posts: 1061
Re: Connecting shapes using GlueTo
« Reply #11 on: July 25, 2012, 10:23:30 AM »
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:
Code: [Select]
page.Drop(shapes[index], element.X, element.Y);
you don't retain a reference to that shape.

With sth. like:
Code: [Select]
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:
Code: [Select]
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

  • Full Member
  • ***
  • Posts: 76
Re: Connecting shapes using GlueTo
« Reply #12 on: July 26, 2012, 07:17:14 AM »
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.