I have to say, I love the Visio ActiveX control. I think it is so cool to be able to make Visio functionality work in the context of your application user interface, rather than have your application conform to the context of the Visio user interface. Especially considering how much heavy lifting goes into the layout and routing algorithms and geometry that sit in the Visio app. You do not want to recreate that functionality in your own app, much less test it. (If you’re interested in learning the basics of the control, check out the Programming with the Visio 2003 ActiveX control article on the Visio developer Web site.)
For Visio 2003, we had a Rapid Adoption Program (RAP) for partners to get kick-started with Visio development and almost all of the partners chose the Visio ActiveX control for development. It just opens up all sorts of options for integrating a visual designer or dashboard into any type of application. I think it’s the most exciting thing for Visio developers since Visio offered support for COM add-ins.
I can go on and on about how great the control is (and trust me, I do at conferences). Here’s my top ten things to think about when you’re working with the control:
- Client-side Control: The control is a client-side control and is not built for or supported in server-side control situations (although the control is supported for Web browsers). It is meant for insertion and use into smart desktop clients that can talk to servers and services. If you want to use the ActiveX control in a server-side situation, you can wrap the control in a Sharepoint Web part (check the Visio dev site for an overview article on this) and use it on Sharepoint. If you want to use the control in a Web part, you HAVE to make sure that your clients have Visio 2003 installed. Otherwise, your clients will get that big fat grey square that says the control is not present.
- Visio user interface in VS.NET containers: You can ONLY negotiate toolbars and menus (merge the Visio toolbars and menus into your custom app) in Visual Basic or C++ applications or Office containers, which are the old OLE containers. You can’t merge Visio toolbars and menus in C# or VB.NET applications. Visio can’t do anything to fix this since it’s part of the Winforms editor implementation – Winforms editor just doesn’t support IOLE2 style menu merging. That doesn’t mean you can’t use C# or VB.NET with the control. Lots of folks do. You just need to know that you will not be able to expose the Visio toolbars and menus in your app. So don’t try to use the control’s NegotiateMenus and NegotiateToolbars properties in VS.NET containers – those two control properties won’t work.
You do have two options for displaying existing Visio’s UI within the control. You can drive the Visio dialogs within the Visio control using DoCmd (see the help file for documentation on DoCmd IDs) to do things like display Visio’s Print dialog. Or you can create a custom toolbar or menu using CommandBars, assign an existing Visio icon to it using the FaceID property, and then program the toolbar or menu entry using the Visio automation model.
- Visio User Interface in Internet Explorer containers: IE has problems trying to negotiate menus (see IE’s KB article for more info). When negotiating menus with IE, you may see two Help menus and sometimes two GoTo menus. Again, not much you can do about this so don’t plan on merging with the Internet Explorer menus; use pop-up menus on your UserDocument instead.
- Displaying multiple documents: The Visio ActiveX control is an SDI. You can’t display multiple documents in the control. If you want to display multiple documents, you have to use multiple instances of the control in your application. There are two things to keep in mind when you are using multiple instances of the control. Only one control instance at a time has focus; and don’t even think about doing menu merging with multiple instances – the underlying Visio application object for the control gets really confused. If you do manage to get the menu merge to actually work, you’ll probably see the toolbars and menus flickering and it isn’t a pretty sight. So when working with multiple instances of the control, don’t try to negotiate toolbars and menus.
- Multiple control instances in IE: Visio is a single threaded application. The control will only work in the first thread of any given iexplore process. If you have IE already running on your computer, and decide to double-click on an html file on your desktop, that file will load in a new thread of IE, not a new process. If that html file uses the Visio control, the control will not work, even if the first thread of the process did not have a control in it. To make sure that the control is going to load properly, you must make sure to create a new IE process and browse/link to the document containing the ActiveX control. Don’t use the Visio FollowHyperlink property (see item 10); create the new IE process in your own custom code.
- “Cleaning” the Control’s Drawing: If you have never initialized a drawing in the control, by default, the control will load a blank drawing. Setting the SRC property to an invalid, or empty string, after it has already been set to some value, does not do anything. It leaves the contents of the control as is. There are three options for loading a blank drawing after you’ve loaded an existing drawing into the control.
- Load a blank drawing by name (“blank.vsd”, for example). This is the most simple option.
- Dynamically destroy and recreate a new instance of the control. Note that this will wipe out any events that you’re synced with for your control. This is a totally blank slate for the control. Use this option when you don’t care about preserving event syncing with your control.
- Select all on the existing drawing and delete the shapes on the Page 1, delete the remaining pages, and then delete the masters and styles as well. If you’re trying to wipe a drawing clean but keep the styles/formatting (“Reset Drawing” functionality), this is the option to choose.
- Persisting Changes in the Control: The only supported way to persist changes to a file loaded in the control is to use the Visio SaveAs method. Once you load a file using SRC, it’s loaded in memory with the control. If you make changes to the drawing without saving the drawing to disk, the changes will not be persisted. That means that if a user closes the file or re-initializes the control, the user loses all the changes because the SRC property tells the control to reload the source drawing and overwrite whatever is there.
It is unsupported by Visio but has been proved possible to persist to stream. If you want to persist the changed document in-stream, reset the SRC property to an empty string. The next time someone uses the control, the person will see the changes in the in-stream version of the document since the source document won’t be loaded. Note that this in-memory document will not be saved to disk unless you explicitly use the Visio SaveAs method. In this case, you would call the SaveAs method and pass in the SRC property as the parameter. Note that this doesn’t apply to IE, really, because in IE you’re just rendering (unless you’re scripting changes).
- Opening Files: You use the SRC property on the control to open up a file. When you set the SRC property, the control loads the contents of that file into the existing instance of the control. It does not "open the file" and keep it open for r/w. It opens a copy of the file at the time the property is set and also at later control-load times. Also, if you want to use a stencil to programmatically drop shapes on your drawing in the control, use Document.OpenEx and make sure you set the parameter flag to make the stencil hidden.
- Figuring Out Documents: Document.Name does not return the correct Document Name. This is the same behavior as embedded Visio. After an insert from file operation in a container app (the most equivalent thing in standalone Visio's world) the Document.Name value is always "VisioDocument". The control's SRC property indicates what drawing was initially loaded (if any) but not necessarily the last SaveAs operation. SaveAs is always "Save a Copy as" when used on an embedded Visio drawing. Also, keep in mind that if you have multiple instances of the control in a single application, they share a common underlying Application object. The result is that things like the documents collection on the application object will reflect the total documents opened across all control instances in your application.
- “You can’t”s: Here’s a brief list of the “you can’t”s for the control. You can’t: programmatically save from the control into a Visio 2002 file format. You will have to save as a Visio 11 document, launch an invisible Visio application, open the Visio 11 document, and save that document as Visio 2002. You can’t: use F5 which maps to "Full Screen Mode" is intentionally disabled (and hidden) from the menus when in-place active for the control. You can’t: use some hot keys like CTRL + F2, which maps to CMD ID 1490 (Print Preview). It is only supported in an in-place active scenario when the container supports IOleCommandTarget and the standard OLECMDID set including a print preview implementation. (see question on print preview). CTRL + P maps to CMD 1010 (File Print). This command should bring up the print dialog, but CTRL + P is not included in our in-place accelerator set by default because it should normally be handled by the container app in an in-place situation. You can’t: use Document.FollowHyperlink. In order for the FollowHyperlink method to work in the control when it is in-place active in a container application, the IOleInPlaceFrame provider by the container must support IServiceProvider. Check the docs for your container to see if it’s supported. We know that it is NOT supported in the Winforms editor. If your container doesn’t have this support, don’t use the Visio implementation to follow hyperlinks. Instead, use other alternatives to achieve the same effect, including IE, Web browser controls, link control, etc.
Automating Print Preview in the control almost made my list because the Visio Automation Model doesn't provide a method for it and control developers want to do this alot, but since it's really a general Visio programming question and there's a code sample in the Visio 2003 SDK in VB.NET, C#, and VB, it didn't make the cut for the list.
This posting is provided "AS IS" with no warranties, and confers no rights.