Logo
HOWTO: Show a modal form from a Visual Studio .NET add-in

Author: Carlos J. Quintero (Microsoft MVP) Applies to: Microsoft Visual Studio .NET 2002
Date: August 2011   Microsoft Visual Studio .NET 2003
Updated: March 2013   Microsoft Visual Studio 2005
      Microsoft Visual Studio 2008
      Microsoft Visual Studio 2010
      Microsoft Visual Studio 2012
Introduction

This article explains how to show a modal form correctly from a Visual Studio add-in, passing the owner window to the ShowDialog method.

More Information

An add-in can show modal windows or toolwindows (modeless windows should be avoided). When showing modally a window using a System.Windows.Forms.Form form, the ShowDialog method must be called, which is overloaded: one variation receives no parameter, and the other one receives the owner window:

(C#)
public System.Windows.Forms.DialogResult ShowDialog(System.Windows.Forms.IWin32Window owner)

(VB.NET)
Public Function ShowDialog(ByVal owner As System.Windows.Forms.IWin32Window) As System.Windows.Forms.DialogResult

It is better to call this variation, because while the other (that doesn't receive the owner window) can work fine most of the time, sometimes (not always) can cause problems when clicking the Visual Studio button on the taskbar of Windows 7, making the Visual Studio window to appear in front of the modal window (hiding it).

The IWin32Window interface has only one member to be implemented: the read-only Handle property that returns a System.IntPtr object that encapsulates a 32-bit or 64-bit pointer or identifier (the handle of the owner window).

In the following sample, the add-in shows a modal window (Form1) when loaded. To do it, the Connect class implements the IWin32Window interface. To get the Visual Studio window you need to use the DTE.MainWindow property, which is a EnvDTE.Window. This class has a hidden HWnd property, that while for toolwindows returns always 0, for the Visual Studio IDE window returns its actual handle:

Language: C#   Copy Code Copy Code (IE only)
 public class Connect : Extensibility.IDTExtensibility2, IWin32Window
{
   private EnvDTE.DTE applicationObject;
   private EnvDTE.AddIn addInInstance;

   public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
   {
      try
      {
         applicationObject = (EnvDTE.DTE)application;
         addInInstance = (EnvDTE.AddIn)addInInst;

         switch (connectMode)
         {
            case ext_ConnectMode.ext_cm_UISetup:

               // Do nothing
               break;

            case ext_ConnectMode.ext_cm_Startup:

               // The add-in was marked to load on startup
               // Do nothing at this point because the IDE may not be fully initialized
               // Visual Studio will call OnStartupComplete when fully initialized
               break;

            case ext_ConnectMode.ext_cm_AfterStartup:

               // The add-in was loaded by hand after startup using the Add-In Manager
               // Initialize it in the same way that when is loaded on startup
               InitializeAddIn();
               break;
         }
      }
      catch (System.Exception e)
      {
         System.Windows.Forms.MessageBox.Show(e.ToString());
      }
   }

   public void OnStartupComplete(ref System.Array custom)
   {
      InitializeAddIn();
   }

   private void InitializeAddIn()
   {
      Form1 frm1; 

      frm1 = new Form1();
      frm1.ShowInTaskbar = false;
      frm1.StartPosition = FormStartPosition.CenterParent;

      using (frm1)
      {
         frm1.ShowDialog(this);
      }
   }
     
   public void OnDisconnection(Extensibility.ext_DisconnectMode RemoveMode, ref System.Array custom)
   {
   }

   public void OnBeginShutdown(ref System.Array custom)
   {
   }

   public void OnAddInsUpdate(ref System.Array custom)
   {
   }

   public System.IntPtr Handle
   {
      get
      { 
         // Wraps the Win32 handle of the Visual Studio main window
         return new System.IntPtr(applicationObject.MainWindow.HWnd);
      }
   }
}
Language: VB.NET   Copy Code Copy Code (IE only)
Public Class Connect
   Implements Extensibility.IDTExtensibility2, IWin32Window

   Private applicationObject As EnvDTE.DTE
   Private addInInstance As EnvDTE.AddIn

   Public Sub OnConnection(ByVal application As Object, ByVal connectMode As Extensibility.ext_ConnectMode, _
      ByVal addInInst As Object, ByRef custom As System.Array) _
      Implements Extensibility.IDTExtensibility2.OnConnection

      Try

         applicationObject = CType(application, EnvDTE.DTE)
         addInInstance = CType(addInInst, EnvDTE.AddIn)

         Select Case connectMode

            Case ext_ConnectMode.ext_cm_UISetup

               ' Do nothing for this add-in with temporary user interface

            Case ext_ConnectMode.ext_cm_Startup

               ' The add-in was marked to load on startup
               ' Do nothing at this point because the IDE may not be fully initialized
               ' Visual Studio will call OnStartupComplete when fully initialized

            Case ext_ConnectMode.ext_cm_AfterStartup

               ' The add-in was loaded by hand after startup using the Add-In Manager
               ' Initialize it in the same way that when is loaded on startup
               InitializeAddIn()

         End Select

      Catch e As System.Exception
         System.Windows.Forms.MessageBox.Show(e.ToString)
      End Try

   End Sub

   Public Sub OnStartupComplete(ByRef custom As System.Array) _
      Implements Extensibility.IDTExtensibility2.OnStartupComplete

      InitializeAddIn()

   End Sub

   Private Sub InitializeAddIn()

      Dim frm1 As Form1

      frm1 = New Form1()
      frm1.ShowInTaskbar = False
      frm1.StartPosition = FormStartPosition.CenterParent

      Using (frm1)

         frm1.ShowDialog(Me)

      End Using

   End Sub

   Public Sub OnDisconnection(ByVal RemoveMode As Extensibility.ext_DisconnectMode, ByRef custom As System.Array) _
      Implements Extensibility.IDTExtensibility2.OnDisconnection
   End Sub

   Public Sub OnBeginShutdown(ByRef custom As System.Array) _
      Implements Extensibility.IDTExtensibility2.OnBeginShutdown
   End Sub

   Public Sub OnAddInsUpdate(ByRef custom As System.Array) _
       Implements Extensibility.IDTExtensibility2.OnAddInsUpdate
   End Sub

   Public ReadOnly Property Handle As System.IntPtr Implements System.Windows.Forms.IWin32Window.Handle
      Get
         ' Wraps the Win32 handle of the Visual Studio main window
         Return New IntPtr(applicationObject.MainWindow.HWnd)
      End Get
   End Property

End Class

Related articles



Go to the 'Visual Studio Extensibility (VSX)' web site for more articles like this (Articles section)


Top