ArcGIS SDK  

Technical Documents

Using modeless Visual Basic dialogs in ArcGIS

At ArcGIS 9.x, Visual Basic for Applications (VBA) is not automatically initialized when ArcGIS applications startup. It will only be initialized if there is at least one VBA subroutine which handles an event such as any document event or those associated with UI Controls. This change was made as part of an overall effort to improve the performance and resource utilization of ArcGIS. At ArcGIS 9.x, many subsystems such as extensions, toolbars and dockable windows are now loaded only when they are actually needed.

Deferring the initialization of VBA when an ArcGIS application starts can cause modeless forms implemented in Visual Basic ActiveX DLLs to fail, since they rely on VBA being fully initialized for modeless support to be enabled. When an attempt is made to show a VB dialog modelessly, the following error will occur;

'Non-modal forms cannot be displayed in this host application from an ActiveX DLL, ActiveX Control, or Property page'

Microsoft documents a known issue where modeless forms in Visual Basic ActiveX DLLs should not be depended on to display modelessly (Refer to Microsoft Knowledge Base Article - 247791 for more information). VB modeless forms also suffer from other problems such as focus and z-order nonconformities. Modeless forms implemented in other development environments—including C++, C#, Delphi and VB.NET--do not suffer from this problem.

In ArcGIS versions prior to 9.0, VBA was loaded at startup in almost all cases, consuming precious resources and lengthening startup time; this however, did provide support for modeless forms implemented in VB DLLs.

Instead of requiring that all users load VBA at application startup in anticipation that a VB modeless form might be required, the following solutions are available to get modeless forms from Visual Basic ActiveX DLLs to appear;

 

ModelessFrame object

The ModelessFrame object was added to ArcGIS 9.0 to provide Visual Basic developers with a way to implement modeless windows in ArcGIS without requiring VBA to initialize, and is essentially a wrapper around ordinary VB forms. The ModelessFrame object requires minimal changes to existing VB code to take advantage of it, manages the Z order of modeless forms so that they behave correctly with respect to application focus, and ensures that the window minimizes and restores appropriately with the ArcGIS application.

Using the ModelessFrame object

The recommended way to implement a ModelessFrame is to define a member variable in the associated VB form, providing an accessor method so that code external to the form can manipulate the modeless frame.

Private m_Form As Form1

 

Private Sub ICommand_OnClick()

  m_Form.Frame.Visible = True

End Sub

 

Private Sub ICommand_OnCreate(ByVal hook As Object)

  Set m_Form = New Form1

End Sub

The following code is defined in the Form1;

Private m_Frame As IModelessFrame

 

Public Function Frame() As IModelessFrame

  If m_Frame Is Nothing Then

    Set m_Frame = New ModelessFrame

    m_Frame.Create Me

    m_Frame.Caption = "Modeless Window"

  End If

  Set Frame = m_Frame

End Function

The ModelessFrame window can be closed several different ways. You can either use the Unload methods on the VB form or simply click on the close button on the form itself. Additionally, the form can be show or hidden using the Visible property on the IModelessFrame interface. The ModelessFrame object also implements the IWindowPostion interface, which can be used to query or modify a window's position and size; this should be used instead of directly manipulating the form itself.

Since the VB form is rehosted within a different window, some VB form properties will not work. This includes the following;

Form.Caption The default title for the window is the value of Form.Caption. However, after the ModelessFrame is created, you must use IModelessFrame.Caption to change the title of the window
Form.Left, Form.Top, Form.Width, Form.Height The window cannot be modified with these properties. Use the equivalent properties on the IWindowPostion interface

 

Preparing your VB form to work with ModelessFrames

When hosting VB forms within any application not written in VisualBasic itself, the Tab index of forms may not be honored correctly. To address this problem, the controls within a form should be created in their Tab index order. Use the 'ESRI Align Controls with Tab Index' VBAddin.

Tabbing will not work for controls that are nested within a container, for example controls that are nested within a frame of a tab strip control. Move these controls out of the containers and place them back onto the form to resolve.

 

Force VBA to load on Startup

As a last resort, you can make VBA load every time the application is started by setting a value in the current users registry settings. Add one or more of the following REG_DWORD keys for each ArcGIS application you want to force VBA loading;

HKEY_LOCAL_MACHINE\Software\ESRI\ArcMap\Settings\PreloadVBA=1 HKEY_LOCAL_MACHINE\Software\ESRI\ArcCatalog\Settings\PreloadVBA=1 HKEY_LOCAL_MACHINE\Software\ESRI\ArcScene\Settings\PreloadVBA=1 HKEY_LOCAL_MACHINE\Software\ESRI\ArcGlobe\Settings\PreloadVBA=1

Since this is a current user setting, as a new user logs in and starts the ArcGIS application the registry key does not exist so VBA will not be loaded. If PreloadVBA has a value of 0; VBA will not be loaded when the application starts. If PreloadVBA has a value of 1; VBA will be loaded when the application starts.