| Author: |
Carlos J. Quintero (Microsoft MVP) |
Applies to: |
Microsoft Visual Studio 2012 |
| Date: |
October 2012 |
|
|
| |
|
|
|
Introduction
This article explains how to get the Microsoft.VisualStudio.Shell.Interop.IVsUIShell5
interface from a Visual Studio 2012 add-in. This interface provides several
methods (GetThemedColor, ThemeWindow, CreateThemedImageList, ThemeDIBits) that
are useful to theme a Visual Studio 2012 add-in when using the Dark / Light
themes.
More information
There are two ways to get the declaration of the SVsUIShell
and IVsUIShell5 types from a Visual Studio 2012 add-in:
1) If your add-in only targets Visual Studio 2012 (and not Visual Studio 2010
and below) then you can safely add a reference to the assembly that contains
this interface, which is the assembly Microsoft.VisualStudio.Shell.Interop.11.0,
Version=11.0.0.0. This assembly resides in the .NET Framework 2.0 Global
Assembly Cache (GAC), in the folder C:\Windows\Assembly, not in the .NET
Framework 4.0 GAC (in the folder C:\Windows\Microsoft.NET\assembly). To add a
reference to an assembly in the GAC 2.0 see the article
HOWTO: Reference a Visual Studio assembly in
the GAC from an add-in. The subfolder that contains the assembly is
GAC_MSIL\Microsoft.VisualStudio.Shell.Interop.11.0\11.0.0.0__b03f5f7f11d50a3a.
2) If you add-in targets several Visual Studio versions with the same dll (see
the article HOWTO: Create an add-in that targets several Visual Studio versions with the same add-in DLL using C# or VB.NET)
then you can not add a reference to the assembly
Microsoft.VisualStudio.Shell.Interop.11.0, Version=11.0.0.0, because that
assembly won't be present on the target computer if Visual Studio 2012 is not
installed. In this case you can define the type in the own code of your add-in
(note: if you use obfuscation, you need to ensure that this type is not
obfuscated):
| Language: VB.NET | Copy Code (IE only) |
Imports System.Runtime.InteropServices
Imports System.Runtime.CompilerServices
<ComVisible(False), Guid("B61FC35B-EEBF-4dec-BFF1-28A2DD43C38F")> _
Public Interface SVsUIShell
End Interface
<StructLayout(LayoutKind.Sequential, Pack:=4), ComConversionLoss()> _
Public Structure VSOPENFILENAMEW
<ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")> _
Public lStructSize As UInt32
<ComConversionLoss()> _
Public hwndOwner As IntPtr
<ComAliasName("Microsoft.VisualStudio.OLE.Interop.LPCWSTR"), MarshalAs(UnmanagedType.LPWStr)> _
Public pwzDlgTitle As String
Public pwzFileName As IntPtr
<ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")> _
Public nMaxFileName As UInt32
<ComAliasName("Microsoft.VisualStudio.OLE.Interop.LPCWSTR"), MarshalAs(UnmanagedType.LPWStr)> _
Public pwzInitialDir As String
<ComAliasName("Microsoft.VisualStudio.OLE.Interop.LPCWSTR"), MarshalAs(UnmanagedType.LPWStr)> _
Public pwzFilter As String
<ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")> _
Public nFilterIndex As UInt32
<ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")> _
Public nFileOffset As UInt32
<ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")> _
Public nFileExtension As UInt32
<ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")> _
Public dwHelpTopic As UInt32
<ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")> _
Public dwFlags As UInt32
End Structure
<ComImport(), Guid("BEC804F7-F5DE-4F3E-8EBB-DAB26649F33F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IVsEnumGuids
<PreserveSig(), MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Function [Next](<[In](), ComAliasName("OLE.ULONG")> ByVal celt As UInt32, <Out(), MarshalAs(UnmanagedType.LPArray, _
SizeParamIndex:=0)> ByVal rgelt As System.Guid(), <Out(), ComAliasName("OLE.ULONG")> ByRef pceltFetched As UInt32) As Integer
<PreserveSig(), MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Function Skip(<[In](), ComAliasName("OLE.ULONG")> ByVal celt As UInt32) As Integer
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Sub Reset()
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Sub Clone(<Out(), MarshalAs(UnmanagedType.Interface)> ByRef ppEnum As IVsEnumGuids)
End Interface
<ComImport(), Guid("2B70EA30-51F2-48BB-ABA8-051946A37283"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IVsUIShell5
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Sub GetOpenFileNameViaDlgEx2(<[In](), Out(), ComAliasName("VsShell.VSOPENFILENAMEW"), _
MarshalAs(UnmanagedType.LPArray)> ByVal openFileName As VSOPENFILENAMEW(), _
<[In](), ComAliasName("OLE.LPCOLESTR"), MarshalAs(UnmanagedType.LPWStr)> ByVal HelpTopic As String, _
<[In](), ComAliasName("OLE.LPCOLESTR"), MarshalAs(UnmanagedType.LPWStr)> ByVal openButtonLabel As String)
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Function GetThemedColor(<[In](), ComAliasName("OLE.REFGUID")> ByRef colorCategory As System.Guid, _
<[In](), ComAliasName("OLE.LPCOLESTR"), MarshalAs(UnmanagedType.LPWStr)> ByVal colorName As String, _
<[In](), ComAliasName("Microsoft.VisualStudio.Shell.Interop.THEMEDCOLORTYPE")> ByVal colorType As UInt32) _
As <ComAliasName("Microsoft.VisualStudio.Shell.Interop.VS_RGBA")> UInt32
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Function GetKeyBindingScope(<[In](), ComAliasName("OLE.REFGUID")> ByRef keyBindingScope As System.Guid) _
As <MarshalAs(UnmanagedType.BStr)> String
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Function EnumKeyBindingScopes() As <MarshalAs(UnmanagedType.Interface)> IVsEnumGuids
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Function ThemeWindow(<[In]()> ByVal hwnd As IntPtr) As Boolean
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Function CreateThemedImageList(<[In]()> ByVal hImageList As IntPtr, _
<[In](), ComAliasName("VsShell.COLORREF")> ByVal crBackground As UInt32) As IntPtr
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Sub ThemeDIBits(<[In](), ComAliasName("OLE.DWORD")> ByVal dwBitmapLength As UInt32, _
<Out(), ComAliasName("TextManager.BYTE"), MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=0)> ByVal pBitmap As Byte(), _
<[In](), ComAliasName("OLE.DWORD")> ByVal dwPixelWidth As UInt32, <[In](), ComAliasName("OLE.DWORD")> ByVal dwPixelHeight As UInt32, _
<[In]()> ByVal fIsTopDownBitmap As Boolean, <[In](), ComAliasName("VsShell.COLORREF")> ByVal crBackground As UInt32)
End Interface
| Language: C# | Copy Code (IE only) |
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[ComVisible(false), Guid("B61FC35B-EEBF-4dec-BFF1-28A2DD43C38F")]
public interface SVsUIShell
{
}
[StructLayout(LayoutKind.Sequential, Pack = 4), ComConversionLoss]
public struct VSOPENFILENAMEW
{
[ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")]
public uint lStructSize;
[ComConversionLoss]
public IntPtr hwndOwner;
[ComAliasName("Microsoft.VisualStudio.OLE.Interop.LPCWSTR"), MarshalAs(UnmanagedType.LPWStr)]
public string pwzDlgTitle;
public IntPtr pwzFileName;
[ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")]
public uint nMaxFileName;
[ComAliasName("Microsoft.VisualStudio.OLE.Interop.LPCWSTR"), MarshalAs(UnmanagedType.LPWStr)]
public string pwzInitialDir;
[ComAliasName("Microsoft.VisualStudio.OLE.Interop.LPCWSTR"), MarshalAs(UnmanagedType.LPWStr)]
public string pwzFilter;
[ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")]
public uint nFilterIndex;
[ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")]
public uint nFileOffset;
[ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")]
public uint nFileExtension;
[ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")]
public uint dwHelpTopic;
[ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")]
public uint dwFlags;
}
[ComImport, Guid("BEC804F7-F5DE-4F3E-8EBB-DAB26649F33F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IVsEnumGuids
{
[PreserveSig, MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
int Next([In, ComAliasName("OLE.ULONG")] uint celt,
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] Guid[] rgelt,
[ComAliasName("OLE.ULONG")] out uint pceltFetched);
[PreserveSig, MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
int Skip([In, ComAliasName("OLE.ULONG")] uint celt);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Reset();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Clone([MarshalAs(UnmanagedType.Interface)] out IVsEnumGuids ppEnum);
}
[ComImport, Guid("2B70EA30-51F2-48BB-ABA8-051946A37283"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IVsUIShell5
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetOpenFileNameViaDlgEx2([In, Out, ComAliasName("VsShell.VSOPENFILENAMEW"),
MarshalAs(UnmanagedType.LPArray)] VSOPENFILENAMEW[] openFileName,
[In, ComAliasName("OLE.LPCOLESTR"), MarshalAs(UnmanagedType.LPWStr)] string HelpTopic,
[In, ComAliasName("OLE.LPCOLESTR"), MarshalAs(UnmanagedType.LPWStr)] string openButtonLabel);
[return: ComAliasName("Microsoft.VisualStudio.Shell.Interop.VS_RGBA")]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
uint GetThemedColor([In, ComAliasName("OLE.REFGUID")] ref Guid colorCategory,
[In, ComAliasName("OLE.LPCOLESTR"), MarshalAs(UnmanagedType.LPWStr)] string colorName,
[In, ComAliasName("Microsoft.VisualStudio.Shell.Interop.THEMEDCOLORTYPE")] uint colorType);
[return: MarshalAs(UnmanagedType.BStr)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
string GetKeyBindingScope([In, ComAliasName("OLE.REFGUID")] ref Guid keyBindingScope);
[return: MarshalAs(UnmanagedType.Interface)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
IVsEnumGuids EnumKeyBindingScopes();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
bool ThemeWindow([In] IntPtr hwnd);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
IntPtr CreateThemedImageList([In] IntPtr hImageList,
[In, ComAliasName("VsShell.COLORREF")] uint crBackground);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void ThemeDIBits([In, ComAliasName("OLE.DWORD")] uint dwBitmapLength,
[Out, ComAliasName("TextManager.BYTE"), MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] pBitmap,
[In, ComAliasName("OLE.DWORD")] uint dwPixelWidth,
[In, ComAliasName("OLE.DWORD")] uint dwPixelHeight,
[In] bool fIsTopDownBitmap,
[In, ComAliasName("VsShell.COLORREF")] uint crBackground);
}
Once you have the interface type definition, to get the service follow the
approach explained in the article HOWTO: Get a Visual Studio service from an add-in.
The following code shows how to call the GetService method:
| Language: VB.NET | Copy Code (IE only) |
Public Class Connect
Implements IDTExtensibility2
Private _applicationObject As DTE
Private _addInInstance As AddIn
Private _IVsUIShell5 As IVsUIShell5
Public Sub OnConnection(ByVal application As Object, ByVal connectMode As ext_ConnectMode, _
ByVal addInInst As Object, ByRef custom As Array) Implements IDTExtensibility2.OnConnection
_applicationObject = CType(application, DTE)
_addInInstance = CType(addInInst, AddIn)
Select Case connectMode
Case ext_ConnectMode.ext_cm_AfterStartup
InitializeAddIn()
Case ext_ConnectMode.ext_cm_Startup
' OnStartupComplete will be called
End Select
End Sub
Public Sub OnStartupComplete(ByRef custom As Array) Implements IDTExtensibility2.OnStartupComplete
InitializeAddIn()
End Sub
Private Sub InitializeAddIn()
Dim service As Object
service = GetService(_applicationObject, GetType(SVsUIShell))
_IVsUIShell5 = CType(service, IVsUIShell5)
End Sub
Public Sub OnDisconnection(ByVal disconnectMode As ext_DisconnectMode, ByRef custom As Array) _
Implements IDTExtensibility2.OnDisconnection
End Sub
Public Sub OnAddInsUpdate(ByRef custom As Array) Implements IDTExtensibility2.OnAddInsUpdate
End Sub
Public Sub OnBeginShutdown(ByRef custom As Array) Implements IDTExtensibility2.OnBeginShutdown
End Sub
End Class
| Language: C# | Copy Code (IE only) |
public class Connect : IDTExtensibility2
{
private DTE2 _applicationObject;
private AddIn _addInInstance;
private IVsUIShell5 _IVsUIShell5;
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
switch (connectMode)
{
case ext_ConnectMode.ext_cm_AfterStartup:
Initialize();
break;
case ext_ConnectMode.ext_cm_Startup:
// OnStartupComplete will be called
break;
}
}
public void OnStartupComplete(ref Array custom)
{
Initialize();
}
private void Initialize()
{
object service = null;
service = GetService(_applicationObject, typeof(SVsUIShell));
_IVsUIShell5 = (IVsUIShell5)service;
}
public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
{
}
public void OnAddInsUpdate(ref Array custom)
{
}
public void OnBeginShutdown(ref Array custom)
{
}
}
Related articles
Go back to the 'Resources for Visual Studio .NET extensibility' section for more articles like this