The Basics of Programming with the DWF Express Viewer Control14 Feb, 2005 By: Mike Tuersley Cadalyst
Now that you've created all those multipage DWF files, let's discuss how to manage them
If you read last month's CAD Clinic, you have lots of DWF files floating around now. And there are probably lots of ways you want to use them. So let's look at how to program with the DWF Express Viewer [EV] that comes with AutoCAD. With it, there is a control included that can be used in your programming (figure 1).
Figure 1. A file as it appears in the DWF Viewer control.
Example Project Scope
To demonstrate how to use the DWF Viewer [EV] control, I'll use a VBA form with 11 CommandButtons, one TabStrip and a TextBox. I'll use 11 buttons because I am going to disable the EV's internal toolbar and code my own commands to demonstrate how to interact with the EV control.
Beware: The EV control is somewhat quirky, and having AutoCAD pop a fatal error when programming with it is not uncommon -- so save often!
To be fair, the problems associated with the control are seemingly related to not completing your code and clearing out the reference to the control. Simplified: Don't stop your program while in debug mode!
These various quirks can be found when using the control with VBA, VB6, VB.NET or C#.
Attaching the EV Control
Once I have started a new project and switched to the form view, I:
- Right-click on the toolbox and select Additional Controls (figure 2).
- In the Additional Controls dialog box, click in the box next to Autodesk DWF Viewer Control if you are in VBA (figure 3). (If you are using VB6 or later, select the ExpressViewerDll 1.0 Type Library.) Click OK.An icon should now be added to the toolbox that can be dragged and dropped into the form.
Figure 2. Adding a control.
Figure 3. Selecting the DWF Viewer control.
Control Quirk #1
This brings us to the first noticeable quirk with the EV control. After placing it on a form, the control may be just a black or white box if you are in VBA or VB6. There are two ways to fix this: either save, close and reload the project or set the control's source path property to a valid DWF file. In NET, the control appears fine but all the Property box information is blank for all the form's controls. In this case, the project must be saved, closed and reopened.
Accessing the EV Control
Most of the time, programmers access a control on the form by calling its name: Me.TextBox1 or Me.CommandButton1, for example. While this can be done with the EV control, there is more functionality available if I use a specific object variable that references it. To do this, I will use the following code on the UserForm Initialize event:
Private dwfViewer As IAdPageViewer2 Private Sub UserForm_Initialize() '+--- Startup ---- 'instantiate instance Set dwfViewer = CExpressViewerControl1.DocumentHandler 'set properties With dwfViewer .BackColor = vbBlack 'turn off toolbar .ToolbarVisible = False 'turn off right-click menu .UserInterfaceEnabled = False End With End Sub
Here I have declared a private variable to reference the EV Control as type IAdPageViewer2. Then, in the form initialize, I set it to the EV Control. After that, I preset some of the EV properties I want, which are commented in the code block above. It is important to note that I could have used the IAdPageViewer object if I knew that my program wouldn't be used to open a multipage DWF file. The IAdPageViewer2 allows additional access to the EV Control for things such as the pages of the multipage DWF file.
Loading a DWF File
I chose to include a TabStrip control so I could mimic the layout tabs in AutoCAD. Although I like the DWF Express/Composer Viewer, I dislike the thumbnails on the side in lieu of the tabs. This allows me to demonstrate how to access the pages within a multipage DWF file.
Sub GetPages() Dim oPage As CAdPage Dim iIndex As Integer 'clear any existing tabs TabStrip1.Tabs.Clear 'iterate pages If dwfViewer.Pages.Count = 1 Then Set oPage = dwfViewer.Pages.Item(1) TabStrip1.Tabs.Add oPage.Name Else For iIndex = 1 To dwfViewer.Pages.Count Set oPage = dwfViewer.Pages.Item(iIndex) TabStrip1.Tabs.Add oPage.Name If iIndex = dwfViewer.Pages.Count Then Exit For Next End If If Not oPage Is Nothing Then Set oPage = Nothing End Sub
The GetPages routine will retrieve all the pages within a multipage DWF file. By declaring a variable of CAdPage type, I can iterate the EV file's PAGE collection. As I iterate each page, I add a tab to the TabStrip and populate it with the name of the CAdPage object -- which is the name of the layout. Normally I could iterate a collection knowing the object it holds like this:
For Each oPage In dwfViewer.Pages ?.do whatever Next
However, using this technique yields unpredictable results with the EV control.
Control Quirk #2
Before the pages of a multipage DWF file can be accessed, the DWF file must be loaded. By looking up the EV Control's methods and properties in the Object Browser, I found a WaitForPageLoaded method. Upon testing it in AutoCAD 2005 on Windows XP, the WaitForPageLoaded will enter an endless loop if the control is placed upon a secondary form that floats in and out of focus.
Autodesk pointed me to the DWF API guide. (What programmer would read an API guide?) In the fine print of the guide, Autodesk recommends using actual events instead of this method. So I tested the OnEndLoadItem event and eventually got it to work. The event will fire twice for each DWF file -- once when the file loads and once for when the page collection loads. By checking the value of the bstrItemName parameter when the event fires, I can tell whether the event is triggered by the document (value = DOCUMENT) or the pages (value = SHEET).
So, I call my GetPages function as a result of the OnEndLoadItem event if it is the DWF document loading, and not the pages:
Private Sub CExpressViewerControl1_OnEndLoadItem _ (ByVal bstrItemName As String, ByVal vData As Variant, _ ByVal vResult As Variant) 'after dwf has loaded, adjust tabs If bstrItemName = "DOCUMENT" Then GetPages End Sub
From here, controlling the EV control is fairly simple. I am providing the user with commandbuttons that start the following commands:
Private Sub cmdPan_Click() dwfViewer.ExecuteCommand ("PAN") End Sub
Private Sub cmdProps_Click() dwfViewer.ExecuteCommand ("PROPERTIES") End Sub
Private Sub cmdZoom_Click() dwfViewer.ExecuteCommand ("ZOOM") End Sub
Private Sub cmdZoomFit_Click() dwfViewer.ExecuteCommand ("FITTOWINDOW") End Sub
Private Sub cmdZoomRect_Click() dwfViewer.ExecuteCommand ("ZOOMRECT") End Sub
6. Switch Layouts
Private Sub TabStrip1_Change() dwfViewer.Page = TabStrip1.Value + 1 End Sub
One final issue remains: printing! That task I will tackle next month. In the meantime, please experiment with the EV Control and see what you can do.