Die Community zu .NET und Classic VB.
Menü

VB.NET-Tipp 0137: Ein Kontextmenu, welches sich die Öffnungsposition merkt

 von 

Beschreibung

Meist beziehen sich Aktionen eines Kontextmenüs nicht auf ein Steuerelement insgesamt, sondern auf ein bestimmtes Element darin (beispielsweise ein Treenode, ListViewItem oder eine DatagridViewCell). Im Click-Ereignis kann man den gemeinten Eintrag aber nicht ohne weiteres identifizieren, denn dazu benötigt man die Mausposition zum Zeitpunkt, als das Kontextmenu geöffnet wurde (die Maus wurde nach dem Öffnen ja weiter bewegt, um ein MenuItem anzuwählen).

Hier wird ein ContextMenuStrip vorgestellt, das sich die Position merkt an der es geöffnet wurde.

Schwierigkeitsgrad:

Schwierigkeitsgrad 1

Framework-Version(en):

.NET Framework 1.0, .NET Framework 1.1, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, .NET Compact Framework 1.0, .NET Compact Framework 2.0, .NET Framework 4

.NET-Version(en):

Visual Basic 2002, Visual Basic 2003, Visual Basic 2005, Visual Basic 2008, Visual Basic 2010

Download:

Download des Beispielprojektes [21,3 KB]

' Dieser Quellcode stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!


' ##############################################################################
' ############################# ContextMenuEx.vb ###############################
' ##############################################################################
Imports System.Drawing
Imports System.ComponentModel

Namespace System.Windows.Forms
    <DesignerCategoryAttribute("Code")> _
    Public Class ContextMenuEx : Inherits ContextMenuStrip

        Private _OpenClickLocation As Point

        Public Sub New()
        End Sub

        ''' <summary>
        ''' the designer uses this constructor to reserve this component
        '''  as to dispose together with the Form
        ''' </summary>
        Public Sub New(ByVal container As IContainer)
            MyBase.New(container)
        End Sub

        ''' <summary>
        ''' mousePosition over the control, on which the ContextMenuEx 
        '''  last time was opened
        ''' </summary>
        Public ReadOnly Property OpenClickLocation() As Point
            Get
                Return _OpenClickLocation
            End Get
        End Property

        Protected Overrides Sub OnOpened(ByVal e As EventArgs)
            If SourceControl IsNot Nothing Then
                _OpenClickLocation = _
                    SourceControl.PointToClient(Control.MousePosition)
            End If
            MyBase.OnOpened(e)
        End Sub
    End Class

End Namespace

' ##############################################################################
' ######################### frmContextMenuExTester.vb ##########################
' ##############################################################################
Public Class frmContextMenuExTester
    ' ContextMenues im FormDesigner erstellen: 
    '  1) ContextMenuEx aus der Toolbox aufs Form ziehen.
    '  2) alle MenuItems darin anlegen, und sinnvoll benennen
    '  3) Doppelklick auf ein Item öffnet den Form-User-Code im Editor, und 
    '      generiert eine Click-Eventhandler-Sub
    '  4) wieder in den FormDesigner wechseln, im EigenschaftenFenster auf 
    '      Events gehen.
    '  5) Die Click-Events der anderen MenuItems dem bereits bestehendem 
    '      Eventhandler zuordnen (Das fügt der Handles-Klausel weitere 
    '      Click-Events hinzu)
    '  6) Die ContextMenustrip-Property des Ziel-Controls auf das passende 
    '     ContextMenuEx festlegen, damit es sich beim Rechtsklick auf dieses 
    '     Control öffnet
    '  7) Im Editor den Eventhandler sinnvoll umbenennen, und die 
    '     Click-Verarbeitung ausprogrammieren

    Private Sub frmContextMenuExTester_Load(ByVal sender As Object, _
            ByVal e As EventArgs) Handles MyBase.Load

        Me.Location = Screen.PrimaryScreen.WorkingArea.Location
        TreeView1.ExpandAll()
    End Sub

    Private Sub TreeviewMenuItem_Click(ByVal sender As Object, _
            ByVal e As EventArgs) Handles btAddNode.Click, btDeleteNode.Click

        Dim nd As TreeNode = TreeView1.GetNodeAt(TreeviewMenu.OpenClickLocation)
        Select Case True
            Case sender Is btAddNode
                Dim Nodes = If(nd Is Nothing, TreeView1.Nodes, nd.Nodes)
                Nodes.Add("NewNode")
                If nd IsNot Nothing Then nd.Expand()

            Case sender Is btDeleteNode
                If nd Is Nothing Then Return
                Dim Nodes = If(nd.Parent Is Nothing, _
                    TreeView1.Nodes, nd.Parent.Nodes)
                Nodes.Remove(nd)
        End Select
    End Sub

    Private Sub ListboxMenuItem_Click(ByVal sender As Object, _
            ByVal e As EventArgs) _
            Handles btListItemUp.Click, btListItemDown.Click, _
                btRemoveListItem.Click, btInsertListItem.Click

        Dim Items = ListBox1.Items
        Dim indx As Integer = _
            ListBox1.IndexFromPoint(ListboxMenu.OpenClickLocation)

        Select Case True
            Case sender Is btInsertListItem
                Static count As Integer = 0
                Items.Insert(If(indx < 0, Items.Count, indx), "NewItem" & count)
                count += 1

            Case sender Is btRemoveListItem
                If indx < 0 Then Return
                Items.RemoveAt(indx)

            Case sender Is btListItemUp
                If indx < 1 Then Return
                Dim itm = Items(indx)
                Items.RemoveAt(indx)
                Items.Insert(indx - 1, itm)

            Case sender Is btListItemDown
                If indx < 0 OrElse indx = Items.Count - 1 Then Return
                Dim itm = Items(indx)
                Items.RemoveAt(indx)
                Items.Insert(indx + 1, itm)
        End Select
    End Sub
End Class

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.