Handling Solid Edge Events
Solid Edge provides a wide range of COM event sets that notify us when certain things occur. In this article, I will discuss how you can attach to these events from .NET. Prior to .NET, handling COM events was rather straightforward. It’s a little tricker in .NET but still completely possible as you’ll see.
For this article, I will be focusing on most popular Solid Edge event set, ISEApplicationEvents.
From .NET, we have two approaches available for connecting to COM events.
- Delegate Event Model
- Connection Point Model
Delegate Event Model
The delegate event model is typically more natural to .NET developers. This approach allows you to handle specific events rather than every event that an event set exposes.
If you open the Object Browser and search for ISEApplicationEvents, you will see the raw interface definition. This raw interface is not what we need in the delegate event model.
There is a hidden class that is generated by the type library importer named ISEApplicationEvents_Event that we need to leverage in this approach. In order to see the hidden class ISEApplicationEvents_Event, modify the Object Browser settings as shown below to Show Hidden Types And Members.
With the Object Browser settings in place, now search for ISEApplicationEvents_Event.
Now that we are aware that ISEApplicationEvents_Event exists, we can leverage it with the following sample code. Please note that the code below is for demonstration purposes only and does not handle situations like when the BeforeQuit event is raised.
*Note that the ISEApplicationEvents_Event class will not be available in the code editor intellisense since it is a hidden class. You will have to manually type the full name and it will resolve.
Visual Basic – Delegate Event Model Example
Imports System
Imports System.Runtime.InteropServices
Imports System.Windows.FormsNamespace EventTest
Partial Public Class Form1
Inherits FormPrivate _application As SolidEdgeFramework.Application
Private _applicationEvents As SolidEdgeFramework.ISEApplicationEvents_EventPublic Sub New()
InitializeComponent()
End SubPrivate Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
‘ Connect to Solid Edge.
_application = DirectCast(Marshal.GetActiveObject(“SolidEdge.Application”), SolidEdgeFramework.Application)‘ Connect to application events.
_applicationEvents = CType(_application.ApplicationEvents, SolidEdgeFramework.ISEApplicationEvents_Event)
AddHandler _applicationEvents.AfterDocumentSave, AddressOf _applicationEvents_AfterDocumentSave
AddHandler _applicationEvents.BeforeDocumentSave, AddressOf _applicationEvents_BeforeDocumentSave
End SubPrivate Sub _applicationEvents_AfterDocumentSave(ByVal theDocument As Object)
‘ Handle AfterDocumentSave.
End SubPrivate Sub _applicationEvents_BeforeDocumentSave(ByVal theDocument As Object)
‘ Handle BeforeDocumentSave.
End SubPrivate Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs)
‘ Disconnect to application events.
RemoveHandler _applicationEvents.BeforeDocumentSave, AddressOf _applicationEvents_BeforeDocumentSave
RemoveHandler _applicationEvents.AfterDocumentSave, AddressOf _applicationEvents_AfterDocumentSave
_applicationEvents = Nothing
End Sub
End Class
End Namespace
C# – Event Delegate Model Example
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;namespace EventTest
{
public partial class Form1 : Form
{
private SolidEdgeFramework.Application _application;
private SolidEdgeFramework.ISEApplicationEvents_Event _applicationEvents;public Form1()
{
InitializeComponent();
}private void Form1_Load(object sender, EventArgs e)
{
// Connect to Solid Edge.
_application = (SolidEdgeFramework.Application)Marshal.GetActiveObject(“SolidEdge.Application”);// Connect to application events.
_applicationEvents = (SolidEdgeFramework.ISEApplicationEvents_Event)_application.ApplicationEvents;
_applicationEvents.AfterDocumentSave += _applicationEvents_AfterDocumentSave;
_applicationEvents.BeforeDocumentSave += _applicationEvents_BeforeDocumentSave;
}void _applicationEvents_AfterDocumentSave(object theDocument)
{
// Handle AfterDocumentSave.
}void _applicationEvents_BeforeDocumentSave(object theDocument)
{
// Handle BeforeDocumentSave.
}private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// Disconnect to application events.
_applicationEvents.BeforeDocumentSave -= _applicationEvents_BeforeDocumentSave;
_applicationEvents.AfterDocumentSave -= _applicationEvents_AfterDocumentSave;
_applicationEvents = null;
}
}
}
Connection Point Model
The Connection Point Model is a more raw, manual approach to handling events. It involves having a class implement an event interface, ISEApplicationEvents in this case. This means you will be handling every event that a particular event set raises.
In order to do this from .NET, we will need to leverage the IConnectionPointContainer and IConnectionPoint interfaces from the System.Runtime.InteropServices.ComTypes namespace.
Visual Basic – Connection Point Model Example
Option Infer OnImports System
Imports System.Runtime.InteropServices
Imports System.Runtime.InteropServices.ComTypes
Imports System.Windows.FormsNamespace EventTest
Partial Public Class Form1
Inherits Form
Implements SolidEdgeFramework.ISEApplicationEventsPrivate _application As SolidEdgeFramework.Application
Private _connectionPoint As IConnectionPoint
Private _cookie As IntegerPublic Sub New()
InitializeComponent()
End SubPrivate Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
‘ Connect to Solid Edge.
_application = DirectCast(Marshal.GetActiveObject(“SolidEdge.Application”), SolidEdgeFramework.Application)ConnectEvents()
End SubPrivate Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs)
DisconnectEvents()
End SubPrivate Sub ConnectEvents()
‘ Get the event GUID.
Dim typeGuid = GetType(SolidEdgeFramework.ISEApplicationEvents).GUID‘ Get a reference to the IConnectionPointContainer.
Dim container As IConnectionPointContainer = DirectCast(_application, IConnectionPointContainer)‘ Lookup the IConnectionPoint.
container.FindConnectionPoint(typeGuid, _connectionPoint)‘ Advise the sink.
_connectionPoint.Advise(Me, _cookie)
End SubPrivate Sub DisconnectEvents()
‘ Unadvise the sink.
_connectionPoint.Unadvise(_cookie)‘ Clear variables.
_cookie = 0
_connectionPoint = Nothing
End Sub#Region “ISEApplicationEvents”
Public Sub AfterActiveDocumentChange(ByVal theDocument As Object)
End SubPublic Sub AfterCommandRun(ByVal theCommandID As Integer)
End SubPublic Sub AfterDocumentOpen(ByVal theDocument As Object)
End SubPublic Sub AfterDocumentPrint(ByVal theDocument As Object, ByVal hDC As Integer, ByRef ModelToDC As Double, ByRef Rect As Integer)
End SubPublic Sub AfterDocumentSave(ByVal theDocument As Object)
End SubPublic Sub AfterEnvironmentActivate(ByVal theEnvironment As Object)
End SubPublic Sub AfterNewDocumentOpen(ByVal theDocument As Object)
End SubPublic Sub AfterNewWindow(ByVal theWindow As Object)
End SubPublic Sub AfterWindowActivate(ByVal theWindow As Object)
End SubPublic Sub BeforeCommandRun(ByVal theCommandID As Integer)
End SubPublic Sub BeforeDocumentClose(ByVal theDocument As Object)
End SubPublic Sub BeforeDocumentPrint(ByVal theDocument As Object, ByVal hDC As Integer, ByRef ModelToDC As Double, ByRef Rect As Integer)
End SubPublic Sub BeforeDocumentSave(ByVal theDocument As Object)
End SubPublic Sub BeforeEnvironmentDeactivate(ByVal theEnvironment As Object)
End SubPublic Sub BeforeQuit()
End SubPublic Sub BeforeWindowDeactivate(ByVal theWindow As Object)
End Sub#End Region
End Class
End Namespace
C# – Connection Point Model Example
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;namespace EventTest
{
public partial class Form1 : Form, SolidEdgeFramework.ISEApplicationEvents
{
private SolidEdgeFramework.Application _application;
private IConnectionPoint _connectionPoint;
private int _cookie;public Form1()
{
InitializeComponent();
}private void Form1_Load(object sender, EventArgs e)
{
// Connect to Solid Edge.
_application = (SolidEdgeFramework.Application)Marshal.GetActiveObject(“SolidEdge.Application”);ConnectEvents();
}private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
DisconnectEvents();
}private void ConnectEvents()
{
// Get the event GUID.
var typeGuid = typeof(SolidEdgeFramework.ISEApplicationEvents).GUID;// Get a reference to the IConnectionPointContainer.
IConnectionPointContainer container = (IConnectionPointContainer)_application;// Lookup the IConnectionPoint.
container.FindConnectionPoint(ref typeGuid, out _connectionPoint);// Advise the sink.
_connectionPoint.Advise(this, out _cookie);
}private void DisconnectEvents()
{
// Unadvise the sink.
_connectionPoint.Unadvise(_cookie);// Clear variables.
_cookie = 0;
_connectionPoint = null;
}#region ISEApplicationEvents
public void AfterActiveDocumentChange(object theDocument)
{
}public void AfterCommandRun(int theCommandID)
{
}public void AfterDocumentOpen(object theDocument)
{
}public void AfterDocumentPrint(object theDocument, int hDC, ref double ModelToDC, ref int Rect)
{
}public void AfterDocumentSave(object theDocument)
{
}public void AfterEnvironmentActivate(object theEnvironment)
{
}public void AfterNewDocumentOpen(object theDocument)
{
}public void AfterNewWindow(object theWindow)
{
}public void AfterWindowActivate(object theWindow)
{
}public void BeforeCommandRun(int theCommandID)
{
}public void BeforeDocumentClose(object theDocument)
{
}public void BeforeDocumentPrint(object theDocument, int hDC, ref double ModelToDC, ref int Rect)
{
}public void BeforeDocumentSave(object theDocument)
{
}public void BeforeEnvironmentDeactivate(object theEnvironment)
{
}public void BeforeQuit()
{
}public void BeforeWindowDeactivate(object theWindow)
{
}#endregion
}
}
Connection Point Model – Option 2
You know I can’t talk about this kind of stuff without mentioning the SolidEdge.Community NuGet Package. It’s situations like this where the open source package shines. The NuGet package installs a class library with pre-built classes to handle scenarios like this. In this particular case, it provides a ConnectionPointController class that makes attaching to COM events very easy.
Visual Basic – Connection Point Model using SolidEdge.Community NuGet Package
Imports SolidEdgeCommunity
Imports System
Imports System.Runtime.InteropServices
Imports System.Windows.FormsNamespace EventTest
Partial Public Class Form1
Inherits Form
Implements SolidEdgeFramework.ISEApplicationEventsPrivate _application As SolidEdgeFramework.Application
Private _connectionPointController As ConnectionPointControllerPublic Sub New()
InitializeComponent()
End SubPrivate Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
‘ Connect to Solid Edge.
_application = DirectCast(Marshal.GetActiveObject(“SolidEdge.Application”), SolidEdgeFramework.Application)_connectionPointController = New ConnectionPointController(Me)
_connectionPointController.AdviseSink(Of SolidEdgeFramework.ISEApplicationEvents)(_application)
End SubPrivate Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs)
_connectionPointController.UnadviseAllSinks()
End Sub#Region “ISEApplicationEvents”
…
#End Region
End Class
End Namespace
C# – Connection Point Model using SolidEdge.Community NuGet Package
using SolidEdgeCommunity;
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;namespace EventTest
{
public partial class Form1 : Form, SolidEdgeFramework.ISEApplicationEvents
{
private SolidEdgeFramework.Application _application;
private ConnectionPointController _connectionPointController;public Form1()
{
InitializeComponent();
}private void Form1_Load(object sender, EventArgs e)
{
// Connect to Solid Edge.
_application = (SolidEdgeFramework.Application)Marshal.GetActiveObject(“SolidEdge.Application”);_connectionPointController = new ConnectionPointController(this);
_connectionPointController.AdviseSink<SolidEdgeFramework.ISEApplicationEvents>(_application);
}private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_connectionPointController.UnadviseAllSinks();
}#region ISEApplicationEvents
…
#endregion
}
}
Conclusion
I was a programmer long before .NET was released and can remember how easy it was handling events from Visual Basic 6 so I can appreciate how some of you might feel after reading this article. To me, this all boils down to change. Yes it is different. Yes it is a bit more code. Yes you have to understand more than you did before .NET. The question is what are you going to do about it? You can either say this is too hard and give up or spend a little time understanding and learning the new techniques to stay relevant. As always, my goal is to be the hand that reaches out says “It’s ok, I’ll help you.”.
Comments