c# and manipulating a .vsd

Started by 0rbital, May 27, 2008, 09:57:27 PM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

0rbital

Hello all,

   I have a task before to take a P&ID drawing in a .vsd file and toggle ouputs on and off displaying the appropriate red/green color for the shape (ie: a valve that the use clicks on) and updating other shape colors based off the input values of 0 or 1.  I have not done any kind of automation with Visio before.  I have the VSD file open through the active X control in my application with no problem but from here I don't understand how I reference all these shapes and change their property values.  It seems like a simple thing to do but none of the examples in the SDK or that I've found on the web really talk about just this application.  Can anyone help me out here?  Say I have a valve on the drawing called V1_2.  How do I actually reference that object in my C# application to change it's foreground color to red or green?

Visio Guy

Hi Orbital,

Here's some posts to get you started:


The key is to access cells in the ShapeSheet of a shape. (select a shape, then choose Window > Show ShapeSheet from the menu)

In your case, you'll be interested in the FillForegnd cell.

You'll also need to get a shape's name or ID, which can be found via Format > Special. You said you've got a valve called V1_2. Is that the text on the shape, or did you actually name it?

Also, here are a few snippets that will make sense eventually:



// Get the currently selected shape:
Visio.Shape shp1 = viscontrol.Window.Selection[1];

// Get a shape by ID = 5:
Visio.Shape shp2 = (Visio.Page)viscontrol.Window.Page.Shapes.ItemFromID(5);

// Get a shape by name = "bob":
Visio.Page pg = (Visio.PageviscontrolWindow.Page;
Visio.Shape shp3 = pg.Shapes["bob"];

// Set the fill color:
shp3.get_Cells("FillForegnd").Formula = "RGB(255,0,0)"  //...red
shp2.get_Cells("FillForegnd").ResultIU= 4  //...built-in value for blue




For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010

0rbital

#2
Quote from: Visio Guy on May 28, 2008, 07:58:35 PM
Hi Orbital,

Here's some posts to get you started:


The key is to access cells in the ShapeSheet of a shape. (select a shape, then choose Window > Show ShapeSheet from the menu)

In your case, you'll be interested in the FillForegnd cell.

You'll also need to get a shape's name or ID, which can be found via Format > Special. You said you've got a valve called V1_2. Is that the text on the shape, or did you actually name it?

Also, here are a few snippets that will make sense eventually:



// Get the currently selected shape:
Visio.Shape shp1 = viscontrol.Window.Selection[1];

// Get a shape by ID = 5:
Visio.Shape shp2 = (Visio.Page)viscontrol.Window.Page.Shapes.ItemFromID(5);

// Get a shape by name = "bob":
Visio.Page pg = (Visio.PageviscontrolWindow.Page;
Visio.Shape shp3 = pg.Shapes["bob"];

// Set the fill color:
shp3.get_Cells("FillForegnd").Formula = "RGB(255,0,0)"  //...red
shp2.get_Cells("FillForegnd").ResultIU= 4  //...built-in value for blue





So to access the shapes do I have to use the drawing control or can I also use the viewer control?  The viewer is much nicer for my application since the user or my code won't be drawing anything just changing colors of the shape based off the click event and setting an IO point on the machine.

thanks!



Visio Guy

The Viewer is much more limited than the drawing control. You might be able to read properties and you can control layers, but I don't think you can draw or move shapes around. You'd have to check - maybe search "automating Visio Viewer" on MSDN or something. I can't remember off hand, since I haven't messed with programming against the viewer in a long time.

For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010

0rbital

Quote from: Visio Guy on June 05, 2008, 04:18:19 PM
The Viewer is much more limited than the drawing control. You might be able to read properties and you can control layers, but I don't think you can draw or move shapes around. You'd have to check - maybe search "automating Visio Viewer" on MSDN or something. I can't remember off hand, since I haven't messed with programming against the viewer in a long time.

Thanks for the help!  After a lot of reading on MSDN I have it up and running where I can make the drawing look how I want in the drawing control and with your examples above I can toggle the selected shapes now. 

Visio Guy

Man, I just read the start of the thread again. I swear I have at least two examples of "Smart Valves" somewhere on my hard drive that need to be turned into Visio Guy articles.

Good luck with your Visio app, Orbital!
For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010

0rbital

Quote from: Visio Guy on June 06, 2008, 09:39:27 PM
Man, I just read the start of the thread again. I swear I have at least two examples of "Smart Valves" somewhere on my hard drive that need to be turned into Visio Guy articles.

Good luck with your Visio app, Orbital!

OK one more hopefully quick question.  I don't want the shapes search and window on the left of the drawing displayed.  How do I get rid of that?

0rbital

Quote from: 0rbital on June 06, 2008, 09:42:45 PM
Quote from: Visio Guy on June 06, 2008, 09:39:27 PM
Man, I just read the start of the thread again. I swear I have at least two examples of "Smart Valves" somewhere on my hard drive that need to be turned into Visio Guy articles.

Good luck with your Visio app, Orbital!

OK one more hopefully quick question.  I don't want the shapes search and window on the left of the drawing displayed.  How do I get rid of that?

Well I can get rid of the shapes search like this:

Visio.Window winShapeSearch = axDrawingControl1.Window.Windows.get_ItemFromID((int)Visio.VisWinTypes.visWinIDShapeSearch);
  winShapeSearch.Visible = false;

But I can't get rid of the shapes below it.  None of the VisWinTypes will do it.  Any ideas?

Visio Guy

Great question, Orbital!

I made a new topic to talk about closing the Shape Search window.

Jump to: Closing the Visio Shape Search Window Programmatically
For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010

0rbital

#9
Man Visio sure is inconsistent.  I got a pointer off the MSDN board but here is how you get rid of the shapes window:

//get rid of shapes window
vsoApp.DoCmd(1669);


Just for reference if you want to show the pan and zoom, close the shape search window, and close shapes window during the form load in C# you would do this:

            // show pan and zoom window
            Visio.Window winPanZoom = axDrawingControl1.Window.Windows.get_ItemFromID((int)Visio.VisWinTypes.visWinIDPanZoom);           
            winPanZoom.Visible = true;
           
            //get rid of shapes search window
            Visio.Window winShapeSearch = axDrawingControl1.Window.Windows.get_ItemFromID((int)Visio.VisWinTypes.visWinIDShapeSearch);
            winShapeSearch.Visible = false;

            //get rid of shapes window
            vsoApp.DoCmd(1669);

0rbital

Also the viewer control does have a limited API that will return the index of the selected shape.  I decided not to use that control but here's the reply from MSDN forums for anyone interested on how to do it:


     The Visio Viewer control does indeed have an API (Microsoft Visio Viewer
12.0 Type Library) that reports back the selected shape (note that the
selection is limited to a single shape in the Viewer)
However, all you get back is the shape index, but you can use the index to
get the custom properties/shape data (and hyperlinks) of the selected
shape...

Private Sub AxViewer1_OnSelectionChanged(ByVal sender As Object, _
ByVal e As
AxVisioViewer._IViewerEvents_OnSelectionChangedEvent) Handles
AxViewer1.OnSelectionChanged
Try
'You can get Me.AxViewer1.CurrentPageIndex
'and e.shapeIndex
'Use Me.AxViewer1.get_CustomPropertyCount(lShape) to get the number of
SHape Data rows
'Loop thru using, or similar,
For lProperty As Integer = 1 To
Me.AxViewer1.get_CustomPropertyCount(lShape)
Dim propName as string .=
Me.AxViewer1.get_CustomPropertyName(lShape, lProperty))
Dim propVal as String =
Me.AxViewer1.get_CustomPropertyValue(e.shapeIndex, lProperty)

Next lProperty

Catch ex As Exception
System.Windows.Forms.MessageBox.Show(ex.InnerException.Message)
End Try
End Sub

0rbital

Ok another strange thing is happening now.  I have an indicator on the page.  I'm setting this shape by ID which is 91.

first the code above to get a shape ID returns a not supported by language compile error:
// Get a shape by ID = 5:
Visio.Shape shp2 = (Visio.Page)viscontrol.Window.Page.Shapes.ItemFromID(5);

So I'm doing it this way:
vsoPage = vsoApp.ActivePage;
shpZ8_604 = vsoPage.Shapes.get_ItemFromID(91);
shpZ8_604.get_Cells("FillForegnd").Formula = "RGB(0,0,255)";

The shape is set correctly when I step through the code off the id but the color will not change. 
Any idea?

0rbital

The problem was the indicators were grouped.  You would think Visio would say something when setting a grouped shapes fillforeground to the effect that hey nothing is going to happen you need to set the colors in the subshapes in the group.  Wasted a lot of my time trying to figure out what was going on since Visio just took the command and did nothing with it.  It should have some sort of exception or warning telling you at least that this is a group shape and nothing will happen with the colors.  That said I now have passed my last hurdle and am actively coding the applications.  Thanks for the help guys.  I'll throw a tidbit of code out for some other P&ID developer now.  My drawings I only need to be concerned about the valves the user can click on to toggle the io point and indicators which show sensor statuses.  On the drawings the tags were all labeled with the names of the valves and sensors but I needed the ID for each one to update their colors.  Instead of looping through them all looking for the tag names I wrote a small bit of code that will go through all the shapes on the page and the ones I needed create a CSV file in the format of the shape.Text,Shape.ID.  Here's the code:

         //This routine will write a text file containing Shape Text, Shape ID  ie V8_604,47 
        //used during developement only on a new drawing to make correlating shape tags and IDs quick
        private void BuildShapesCSVFile()
        {
            sw = new StreamWriter("textfilename.txt");
            foreach (Visio.Shape shp in vsoPage.Shapes)
            {
                if (shp.NameU.Contains("valve") || shp.NameU.Contains("Indicator"))
                {
                    sw.WriteLine(shp.Text + "," + Convert.ToString(shp.ID));
                }
            }
            sw.Close();
        }

0rbital

#13
The final hurdle for me was to get a group shape comprised of 2 group shapes to color red or green.  This requires two for loops here's how I'm doing it.  Hopefully this will make anyone else looking for this information happy instead of my trial and error and posting for help  :)
       
        private string Red = "RGB(255,0,0)";

        //two ids needed for each group shape inside the main group shape
        private Visio.Shape shpLS5_2;
        short idFLS5_2_p1 = 654;
        short idFLS5_2_p2 = 657;

            //LS5_2 group shape requires 2 loops 1 for each group shape
            shpLS5_2 = vsoPage.Shapes.get_ItemFromID(idFLS5_2_p1);

            for (int shapeCounter = 1; shapeCounter < shpLS5_2.Shapes.Count + 1; shapeCounter++)
            {
                shpLS5_2.Shapes[shapeCounter].get_Cells("FillForegnd").Formula = Red;
            }

            shpLS5_2 = vsoPage.Shapes.get_ItemFromID(idFLS5_2_p2);

            for (int shapeCounter = 1; shapeCounter < shpLS5_2.Shapes.Count + 1; shapeCounter++)
            {
                shpLS5_2.Shapes[shapeCounter].get_Cells("FillForegnd").Formula = Red;
            }