Understanding Visio Event Model

In the previous chapters we have already seen an important Visio event, DocumentOpened, which is triggered each time you open a new diagram. However, the Visio API supports tons of other events and some of them are necessary for building sophisticated applications around Visio. Provided you have an application with an embedded Visio control and users can use the application to modify diagrams. Obviously, you want to keep track of such changes and, say, record them in a database. Visio events allows you to receive notifications every time such a change occurs.

SelectionChanged

However, we postpone fancy diagram editing to a later stage. Instead we’ll start with a simple yet rather important event that fires when a user selects or deselects shape in a diagram.

The event is called SelectionChanged and you write down the following code in order to handle it:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    this.visioControl.SelectionChanged += new EVisOcx_SelectionChangedEventHandler(visioControl_SelectionChanged);
}

While the handler itself may look in the following way:

private void visioControl_SelectionChanged(object sender, EVisOcx_SelectionChangedEvent e)
{
    MessageBox.Show("You have selected " + e.window.Selection.Count.ToString() + " shape(s)");
    MessageBox.Show("Which are/is");

    foreach (Visio.Shape shape in e.window.Selection)
    {
        MessageBox.Show(shape.Text + " (" + shape.Name + ")");
    }
}

Here we receive a parameter e of type EvisOcx_SelectionChangedEvent that allows us to get access to a current object of class Selection that was already mentioned in the previous tutorial. As a result, we can always get a number of selected shapes and iterate through them. It is clear that if a user drops a selection, that object will contain no shapes at all.

ShapeAdded

This event is triggered by adding new shapes into a diagram. Although it hasn’t been shown yet, but it is possible incorporate a Visio window for adding shapes in your application.

screenshot

Moreover, this is not the only trigger for the event. Every time you paste something into a diagram including already present the event is fired. So, you can try it now without having to draw that shapes window.

this.visioControl.ShapeAdded += new EVisOcx_ShapeAddedEventHandler(visioControl_ShapeAdded);

I wrote the following event handler that simply outputs a name of a newly added or pasted shape:

private void visioControl_ShapeAdded(object sender, EVisOcx_ShapeAddedEvent e)
{
    MessageBox.Show("You have added a new shape which is " + e.shape.Name);
}

As with SelectionChanged the second parameter of the handler contains useful information about the event, in particular you can access a newly added shape.

Detecting Shape Movements, Resizing, and etc.

The Visio API doesn’t have an event, like ShapeMoved or ShapeResized. Instead, there is an event called CellChanged that consumes almost every event related to changing the way a shape looks. Each shape has a property, Cell, that contains data about a shape’s size, fill colour, line colour, coordinates, and etc. This data is represented as a spreadsheet, where Cell.Name refers to a property name (e.g. Width), while Cell.Formula holds its values. You can find more information about that on MSDN. Obviously, when moving a shape around a diagram this property changes. Moreover, the event can fire a few times depending on how many properties have been changed.

If we want to detect a movement we are interested only in PinX and PinY that represent the centre of rotation of a shape.

this.visioControl.Window.Application.CellChanged += new Visio.EApplication_CellChangedEventHandler(Application_CellChanged);
//...
private void Application_CellChanged(Visio.Cell cell)
{
    if (cell.Name == "PinX" || cell.Name == "PinY")
    {
        MessageBox.Show(cell.Shape.Name + " has been moved");
    }
}

Moreover, it is also possible to check which shape has been really moved by accessing `cell.Shape``.

Shape Caption Change

Often, it is useful to track when a user changes a shape caption (or Shape.Text in the API terminology). There is a convenient event, ShapeExitedTextEdit, that, as the title suggests, fires when a user exits a textbox for editing a caption.

this.visioControl.ShapeExitedTextEdit += new EVisOcx_ShapeExitedTextEditEventHandler(visioControl_ShapeExitedTextEdit);

//...

private void visioControl_ShapeExitedTextEdit(object sender, EVisOcx_ShapeExitedTextEditEvent e)
{
    MessageBox.Show(e.shape.Name + "'s text has been chaged");
}

BeforeShapeDelete

Finally, if you feel you some shape in your diagram is not needed anymore, you can easily delete it and most importantly handle that event.

this.visioControl.Window.Application.BeforeShapeDelete += new Visio.EApplication_BeforeShapeDeleteEventHandler(Application_BeforeShapeDelete);

//...

private void Application_BeforeShapeDelete(Visio.Shape shape)
{
    MessageBox.Show(shape.Name + " has been deleted");
}

Source Code

Conclusion

The Visio event model allows you to build rich interaction between your application and a hosted Visio control. You can freely allow users to edit diagrams in your application and the application itself will be notified about every change.

Mike Borozdin (Twitter)
7 September 2011

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way. My personal thoughts tend to change, hence the articles in this blog might not provide an accurate reflection of my present standpoint.

© Mike Borozdin