DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

どのコントロールを右クリックしてコンテキストメニューを表示したかを調べる

コントロールのContextMenuStripプロパティ(.NET Framework 1.1以前では、ContextMenuプロパティ)を使用してコンテキストメニューを表示している時、どのコントロールを右クリックしてコンテキストメニューを表示したかを調べる方法を紹介します。例えば、複数のコントロールで同じContextMenuStripを使用している時に役に立ちます。

.NET Framework 2.0以降で、ContextMenuStripコントロールの場合

ContextMenuStrip.SourceControlプロパティにより、ContextMenuStripを表示しているコントロールを取得できます。

ContextMenuStripを表示する直前に、そのContextMenuStripを表示しようとしているコントロールを取得する例を示します。この例では、「ContextMenuStrip1」というContextMenuStripがすでに存在しているものとして、ContextMenuStrip1のOpeningイベントが発生した時(コンテキストメニューが表示された時)、ContextMenuStripを表示しようとしているコントロールの名前を表示しています。

VB.NET
コードを隠すコードを選択
'ContextMenuStrip1のOpeningイベントハンドラ
Private Sub ContextMenuStrip1_Opening(sender As Object, e As CancelEventArgs) _
    Handles ContextMenuStrip1.Opening

    Dim menu As ContextMenuStrip = DirectCast(sender, ContextMenuStrip)
    'ContextMenuStripを表示しているコントロールを取得する
    Dim source As Control = menu.SourceControl
    If source IsNot Nothing Then
        Console.WriteLine(source.Name)
    End If
End Sub
C#
コードを隠すコードを選択
//ContextMenuStrip1のOpeningイベントハンドラ
private void ContextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
    ContextMenuStrip menu = (ContextMenuStrip)sender;
    //ContextMenuStripを表示しているコントロールを取得する
    Control source = menu.SourceControl;
    if (source != null)
    {
        Console.WriteLine(source.Name);
    }
}

もう一つ例を示します。今度は、ContextMenuStripの項目(ToolStripMenuItem)がクリックされた時、そのContextMenuStripを表示したコントロールを取得する例です。ここでは、ContextMenuStrip(ContextMenuStrip1)に「CommandToolStripMenuItem」という項目が存在しているものとして、そのClickイベントが発生した時にContextMenuStripを表示したコントロールの名前を表示しています。

VB.NET
コードを隠すコードを選択
'ToolStripMenuItemのClickイベントハンドラ
Private Sub CommandToolStripMenuItem_Click(sender As Object, e As EventArgs) _
    Handles CommandToolStripMenuItem.Click

    'ContextMenuStripを表示しているコントロールを取得する
    Dim source As Control = ContextMenuStrip1.SourceControl
    If source IsNot Nothing Then
        Console.WriteLine(source.Name)
    End If
End Sub
C#
コードを隠すコードを選択
//ToolStripMenuItemのClickイベントハンドラ
private void CommandToolStripMenuItem_Click(object sender, EventArgs e)
{
    //ContextMenuStripを表示しているコントロールを取得する
    Control source = contextMenuStrip1.SourceControl;
    if (source != null)
    {
        Console.WriteLine(source.Name);
    }
}

子項目をクリックした時、SourceControlがnullになる問題

上記最後の例で、CommandToolStripMenuItemがContextMenuStripの項目の子項目(入れ子になった項目)だった場合、SourceControlプロパティがnullになってしまいます。この問題の解決法は、不明です。しかしContextMenuStripのOpeningやOpenedイベントではSourceControlプロパティで正しく取得できますので、この時にSourceControlプロパティの内容を覚えておくという方法で回避できます。

この方法で問題を回避した例を示します。

VB.NET
コードを隠すコードを選択
'Openedイベント時点でのContextMenuStrip.SourceControlプロパティの内容
Private contextMenuSourceControl As Control = Nothing

'ContextMenuStrip1のOpenedイベントハンドラ
Private Sub ContextMenuStrip1_Opened(sender As Object, e As EventArgs) _
    Handles ContextMenuStrip1.Opened

    Dim menu As ContextMenuStrip = DirectCast(sender, ContextMenuStrip)
    'SourceControlプロパティの内容を覚えておく
    contextMenuSourceControl = menu.SourceControl
End Sub

'ToolStripMenuItemのClickイベントハンドラ
Private Sub CommandToolStripMenuItem_Click(sender As Object, e As EventArgs) _
    Handles CommandToolStripMenuItem.Click

    'ContextMenuStripを表示しているコントロールを取得する
    If contextMenuSourceControl IsNot Nothing Then
        Console.WriteLine(contextMenuSourceControl.Name)
    End If
End Sub
C#
コードを隠すコードを選択
//Openedイベント時点でのContextMenuStrip.SourceControlプロパティの内容
private Control contextMenuSourceControl = null;

//ContextMenuStrip1のOpenedイベントハンドラ
private void ContextMenuStrip1_Opened(object sender, CancelEventArgs e)
{
    ContextMenuStrip menu = (ContextMenuStrip)sender;
    //SourceControlプロパティの内容を覚えておく
    contextMenuSourceControl = menu.SourceControl;
}

//ToolStripMenuItemのClickイベントハンドラ
private void CommandToolStripMenuItem_Click(object sender, EventArgs e)
{
    //ContextMenuStripを表示しているコントロールを取得する
    if (contextMenuSourceControl != null)
    {
        Console.WriteLine(contextMenuSourceControl.Name);
    }
}

ContextMenuコントロールの場合

ContextMenu.SourceControlプロパティにより、ContextMenuを表示しているコントロールを取得できます。

VB.NET
コードを隠すコードを選択
'ContextMenu1のPopupイベントハンドラ
Private Sub ContextMenu1_Popup(ByVal sender As Object, _
        ByVal e As System.EventArgs) _
        Handles ContextMenu1.Popup
    'ContextMenuを表示しているコントロールを表示する
    Console.WriteLine(ContextMenu1.SourceControl.Name)
End Sub
C#
コードを隠すコードを選択
//ContextMenu1のPopupイベントハンドラ
private void ContextMenu1_Popup(object sender, System.EventArgs e)
{
    //ContextMenuを表示しているコントロールを表示する
    Console.WriteLine(ContextMenu1.SourceControl.Name);
}

なお、.NET Framework 1.1以前では、RichTextBoxコントロールではSourceControlプロパティが正しく返されません。2.0では、修正されました。

  • 履歴:
  • 2014/9/28 ToolStripMenuItemがクリックされた後に取得する例を追加。「子項目をクリックした時、SourceControlがnullになる問題」を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。