Visual Studio 2008 のアドインを作成する。右クリックメニュー(コンテキストメニュー)にユーザ定義の項目を追加する。

Visual Studio 2008 の各種右クリックメニューを拡張するには、CommandBarsコレクションの追加したいコンテキストメニューにcommandBarButtonを追加して対応します。

今回はソリューションエクスプローラの右クリックメニューを拡張します。ソリューション、プロジェクト、プロジェクトの項目を選択して右クリックを押した際に、以下のようなメニューを追加したいと思います。

追加するネストは、以下の記事で説明しているコマンドバーのダンプから探します。

Visual Studio 2008 のアドインを作成する。コマンドバーの構成。
http://d.hatena.ne.jp/tekk/20091030/1256910708

調べた結果、それぞれの右クリックメニューは以下のような深いネストの下にあることが分かります。

[CommandBars]-[Context Menus]-[プロジェクトとソリューション コンテキスト メニュー]-[ソリューション]
[CommandBars]-[Context Menus]-[プロジェクトとソリューション コンテキスト メニュー]-[プロジェクト]
[CommandBars]-[Context Menus]-[プロジェクトとソリューション コンテキスト メニュー]-[項目]

[CommandBars]-[Context Menus]の取得


Dim commandBars As CommandBars = CType(_applicationObject.CommandBars, CommandBars)
Dim menuBarCommandBar As CommandBar = commandBars.Item("MenuBar")
Dim contextCommandBar As CommandBar = commandBars.Item("Context Menus")

[ソリューション],[プロジェクト],[項目]の取得


Dim projectSolutionPopup As CommandBarPopup = CType(contextCommandBar.Controls.Item("プロジェクトとソリューション コンテキスト メニュー"), CommandBarPopup)
Dim solutionPopup As CommandBarPopup = CType(projectSolutionPopup.Controls.Item("ソリューション"), CommandBarPopup)
Dim projectPopup As CommandBarPopup = CType(projectSolutionPopup.Controls.Item("プロジェクト"), CommandBarPopup)
Dim itemPopup As CommandBarPopup = CType(projectSolutionPopup.Controls.Item("項目"), CommandBarPopup)

サンプルコード


Imports System
Imports Microsoft.VisualStudio.CommandBars
Imports Extensibility
Imports EnvDTE
Imports EnvDTE80

Public Class Connect

Implements IDTExtensibility2
Implements IDTCommandTarget

Dim _applicationObject As DTE2
Dim _addInInstance As AddIn

Private _windowToolWindow As Window = Nothing
Private _addinControl As AddinUserControl = Nothing

'''

アドイン オブジェクトのコンストラクタを実装します。初期化コードをこのメソッド内に配置してください。
Public Sub New()

End Sub

'''

IDTExtensibility2 インターフェイスの OnConnection メソッドを実装します。アドインが読み込まれる際に通知を受けます。
'''ホスト アプリケーションのルート オブジェクトです。
'''アドインの読み込み状態を説明します。
'''このアドインを表すオブジェクトです。
'''
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, DTE2)
_addInInstance = CType(addInInst, AddIn)

If connectMode = ext_ConnectMode.ext_cm_UISetup Then

'コマンドを [ツール] メニューに配置します。
'メイン メニュー項目のすべてを保持するトップレベル コマンド バーである、MenuBar コマンド バーを検索します:
Dim commandBars As CommandBars = CType(_applicationObject.CommandBars, CommandBars)
Dim menuBarCommandBar As CommandBar = commandBars.Item("MenuBar")
Dim contextCommandBar As CommandBar = commandBars.Item("Context Menus")

Try
'コマンド コレクションにコマンドを追加します:
Dim commands As Commands2 = CType(_applicationObject.Commands, Commands2)

Dim toolsPopup As CommandBarPopup = CType(menuBarCommandBar.Controls.Item("ツール"), CommandBarPopup)
Dim command As Command = commands.AddNamedCommand2(_addInInstance, "MyAddin1", "MyAddin1", "Executes the command for MyAddin1", True, 59, Nothing, CType(vsCommandStatus.vsCommandStatusSupported, Integer) + CType(vsCommandStatus.vsCommandStatusEnabled, Integer), vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton)

Dim projectSolutionPopup As CommandBarPopup = CType(contextCommandBar.Controls.Item("プロジェクトとソリューション コンテキスト メニュー"), CommandBarPopup)
Dim solutionPopup As CommandBarPopup = CType(projectSolutionPopup.Controls.Item("ソリューション"), CommandBarPopup)
Dim projectPopup As CommandBarPopup = CType(projectSolutionPopup.Controls.Item("プロジェクト"), CommandBarPopup)
Dim itemPopup As CommandBarPopup = CType(projectSolutionPopup.Controls.Item("項目"), CommandBarPopup)

Dim solutionDiffCommandButton As Command = Nothing

solutionDiffCommandButton = commands.AddNamedCommand2(_addInInstance, _
"solutionDiffButton", _
"WinMergeで比較する", _
String.Empty, _
True, _
137, _
Nothing, _
CType(vsCommandStatus.vsCommandStatusSupported, Integer) + CType(vsCommandStatus.vsCommandStatusEnabled, Integer), _
vsCommandStyle.vsCommandStylePictAndText, _
vsCommandControlType.vsCommandControlTypeButton)

solutionDiffCommandButton.AddControl(solutionPopup.CommandBar, 1)

Dim projectDiffCommandButton As Command = Nothing

projectDiffCommandButton = commands.AddNamedCommand2(_addInInstance, _
"projectDiffButton", _
"WinMergeで比較する", _
String.Empty, _
True, _
137, _
Nothing, _
CType(vsCommandStatus.vsCommandStatusSupported, Integer) + CType(vsCommandStatus.vsCommandStatusEnabled, Integer), _
vsCommandStyle.vsCommandStylePictAndText, _
vsCommandControlType.vsCommandControlTypeButton)

projectDiffCommandButton.AddControl(projectPopup.CommandBar, 1)

Dim itemDiffCommandButton As Command = Nothing

itemDiffCommandButton = commands.AddNamedCommand2(_addInInstance, _
"itemDiffButton", _
"WinMergeで比較する", _
String.Empty, _
True, _
137, _
Nothing, _
CType(vsCommandStatus.vsCommandStatusSupported, Integer) + CType(vsCommandStatus.vsCommandStatusEnabled, Integer), _
vsCommandStyle.vsCommandStylePictAndText, _
vsCommandControlType.vsCommandControlTypeButton)

itemDiffCommandButton.AddControl(itemPopup.CommandBar, 1)

'MenuBar コマンド バーで適切なコマンド バーを検索します:
command.AddControl(toolsPopup.CommandBar, 1)
Catch argumentException As System.ArgumentException
'同じ名前のコマンドが既に存在しているため、例外が発生した可能性があります。
' その場合、コマンドを再作成する必要はありません。 例外を
' 無視しても安全です。
End Try

End If
End Sub

'''

IDTExtensibility2 インターフェイスの OnDisconnection メソッドを実装します。アドインがアンロードされる際に通知を受けます。
'''アドインのアンロード状態を説明します。
'''ホスト アプリケーション固有のパラメータの配列です。
'''
Public Sub OnDisconnection(ByVal disconnectMode As ext_DisconnectMode, ByRef custom As Array) Implements IDTExtensibility2.OnDisconnection

Try

If Not _windowToolWindow Is Nothing Then
_windowToolWindow.Visible = False
_windowToolWindow.Close()
End If

If Not _addinControl Is Nothing Then
_addinControl.Visible = False
_addinControl.Dispose()
End If

Catch ex As Exception

End Try

End Sub

'''

IDTExtensibility2 インターフェイスの OnAddInsUpdate メソッドを実装します。アドインのコレクションが変更されたときに通知を受けます。
'''ホスト アプリケーション固有のパラメータの配列です。
'''
Public Sub OnAddInsUpdate(ByRef custom As Array) Implements IDTExtensibility2.OnAddInsUpdate
End Sub

'''

IDTExtensibility2 インターフェイスの OnStartupComplete メソッドを実装します。ホスト アプリケーションが読み込みを終了したときに通知を受けます。
'''ホスト アプリケーション固有のパラメータの配列です。
'''
Public Sub OnStartupComplete(ByRef custom As Array) Implements IDTExtensibility2.OnStartupComplete
End Sub

'''

IDTExtensibility2 インターフェイスの OnBeginShutdown メソッドを実装します。ホスト アプリケーションがアンロードされる際に通知を受けます。
'''ホスト アプリケーション固有のパラメータの配列です。
'''
Public Sub OnBeginShutdown(ByRef custom As Array) Implements IDTExtensibility2.OnBeginShutdown
End Sub

'''IDTCommandTarget インターフェイスの QueryStatus メソッドを実装します。これは、コマンドの可用性が更新されたときに呼び出されます。
'''状態を決定するためのコマンド名です。
'''コマンドに必要なテキストです。
'''ユーザー インターフェイス内のコマンドの状態です。
'''neededText パラメータから要求されたテキストです。
'''
Public Sub QueryStatus(ByVal commandName As String, ByVal neededText As vsCommandStatusTextWanted, ByRef status As vsCommandStatus, ByRef commandText As Object) Implements IDTCommandTarget.QueryStatus
If neededText = vsCommandStatusTextWanted.vsCommandStatusTextWantedNone Then

Dim list As New System.Collections.Generic.List(Of String)

list.Add("MyAddin1.Connect.MyAddin1")
list.Add("MyAddin1.Connect.solutionDiffButton")
list.Add("MyAddin1.Connect.projectDiffButton")
list.Add("MyAddin1.Connect.itemDiffButton")

If list.Contains(commandName) = True Then
status = CType(vsCommandStatus.vsCommandStatusEnabled + vsCommandStatus.vsCommandStatusSupported, vsCommandStatus)
Else
status = vsCommandStatus.vsCommandStatusUnsupported
End If
End If
End Sub

'''

IDTCommandTarget インターフェイスの Exec メソッドを実装します。これは、コマンドが実行されるときに呼び出されます。
'''実行するコマンド名です。
'''コマンドの実行方法を説明します。
'''呼び出し元からコマンド ハンドラへ渡されたパラメータです。
'''コマンド ハンドラから呼び出し元へ渡されたパラメータです。
'''コマンドが処理されたかどうかを呼び出し元に通知します。
'''
Public Sub Exec(ByVal commandName As String, ByVal executeOption As vsCommandExecOption, ByRef varIn As Object, ByRef varOut As Object, ByRef handled As Boolean) Implements IDTCommandTarget.Exec
handled = False
If executeOption = vsCommandExecOption.vsCommandExecOptionDoDefault Then
If commandName = "MyAddin1.Connect.MyAddin1" Then

If _addinControl Is Nothing Then

Dim programmableObject As Object = Nothing
Dim window2 As EnvDTE80.Windows2 = Nothing
Dim asm As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()

window2 = CType(_applicationObject.Windows, EnvDTE80.Windows2)
_windowToolWindow = window2.CreateToolWindow2(_addInInstance, _
asm.Location, _
"MyAddin1.AddinUserControl", _
"AddinTest", _
"{9A2ABD9B-1841-4f59-85D8-CA566310BC09}", _
programmableObject)

_addinControl = CType(programmableObject, AddinUserControl)
_addinControl.Application = _applicationObject
_addinControl.AddinInstance = _addInInstance

_windowToolWindow.Visible = True

Else

_windowToolWindow.Visible = Not _windowToolWindow.Visible

End If

handled = True
Exit Sub
End If
ElseIf commandName = "MyAddin1.Connect.solutionDiffButton" Then
ElseIf commandName = "MyAddin1.Connect.projectDiffButton" Then
ElseIf commandName = "MyAddin1.Connect.itemDiffButton" Then

End If

End Sub
End Class