3 4
One way to handle Microsoft Visio events in a C++ program is to use Event objects. An Event object pairs an event code with an action—either to run an add-on or to notify another object, called a sink object, whenever the specified event has occurred. For a discussion of how Event objects work and details about implementing them in Microsoft Visual Basic programs, see Chapter 21, Handling Visio Events.
The protocols the Visio engine uses to support the Visual Basic WithEvents style of event handling are the standard IConnectionPoint protocols provided by controls and used by control containers. As an alternative to using Event objects, a C++ program can receive events from a Visio instance using IConnectionPoint protocols, but it must implement the entire event-set interface declared for the type of Visio object from which it wants to receive events. For details about IConnectionPoint and related interfaces, see your Component Object Model (COM) documentation.
The topics in this section describe how to receive Visio events in C++ programs using Event objects that are established by calling EventList.Add or EventList.AddAdvise. Although this protocol is specific to Visio, a C++ program need not implement entire event-set interfaces; instead, the C++ program can register for just the events of interest rather than every event in an event set, which IConnectionPoint requires.
You implement handling of Visio events in a C++ program in much the same way as in a Visual Basic program, with these exceptions:
STDMETHOD(VisEventProc) ( WORD wEvent, //Event code of the event that is firing IUnknown FAR* ipSource, //Pointer to IUnknown on object firing the event DWORD dwEventID, //The ID of the event that is firing DWORD dwSeq, //The sequence number of the event IUnknown FAR* ipSubject, //Pointer to IUnknown on event subject VARIANT VextraInfo //Additional information (usually a context string) );
When you call AddAdvise to create the Event object, you pass a pointer to the IUnknown or IDispatch interface on the sink object.
Beginning with Microsoft Visio 2000, instead of implementing your own sink object, you can use the CVisioAddonSink class provided with Visio. This class is declared in the file Addsink.h in \Libraries\C-CPP\Vao_inc on the Developing Microsoft Visio Solutions CD.
The sample program Generic.cpp uses CVisioAddonSink to handle two events: DocumentCreated and ShapeAdded. The program declares a callback functionfor each event. The signature of the callback function must conform to visEventProc, which is defined in Addsink.h. The following example shows one of the declarations. For the implementation of this function, see Generic.cpp.
HRESULT STDMETHODCALLTYPE ReceiveNotifyFromVisio ( IUnknown FAR* IpSink, WORD wEvent, IUnknown FAR* ipSource, DWORD nEventID, DWORD dwEventSeq, IUnknown FAR* ipSubject, VARIANT eventExtra);
To create the sink object, the program gets the EventList collection of the Application object (represented by the CVisioApplication variable app), calls CoCreateAddonSink to create the sink object, and calls AddAdvise on the EventList collection to create the Event object in the Visio instance. The program sets a flag, bFirstTime, to ensure that the Event objects are created only once while the program is running. The ID of the Event object is stored in the static variable stc_nEventID for later reference. The AddAdvise call creates a second reference on the sink object, so the program can release pSink :
static long stc_nEventID = visEvtIDInval; IUnknown FAR* pSink = NULL; IUnknown FAR* pAnotherSink = NULL; static BOOL bFirstTime = TRUE; CVisioApplication app; CVisioEventList eList; CVisioEvent event; ... if (bFirstTime && (SUCCEEDED(app.EventList(eList)))) { bFirstTime= FALSE; if (SUCCEEDED(CoCreateAddonSink(ReceiveNotifyFromVisio, &pSink))) { if (SUCCEEDED(eList.AddAdvise(visEvtCodeDocCreate, VVariant(pSink), VBstr(""), VBstr(""), event))) { event.ID(&stc_nEventID); } //If AddAdvise succeeded, Visio now holds a reference to //the sink object //via the event object, and pSink can be released pSink->Release(); pSink= NULL; } ... }
Event objects created with AddAdvise persist until the Event object is deleted, all references to the source object are released, or the Visio instance is closed. If your program needs to perform cleanup tasks before the Visio instance is closed, handle the BeforeQuit event.
If CVisioAddonSink is used in a Visio library (VSL), its unload handler must call Event.Delete.
For more information on Visio methods, events, and objects, see the Microsoft Visio Developer Reference (on the Help menu, click Developer Reference).