vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#

https://www.vbarchiv.net
Rubrik:    |   VB-Versionen: VB2005, VB200802.06.09
Rechtsklick auf Spaltenbezeichner im ListView abfangen

Das ListView-Control bietet leider kein Möglichkeit, gezielt auf einen Rechtsklick innerhalb der Spaltenbezeichner zu reagieren. Diese Tipp schafft Abhilfe!

Autor:  Dieter OtterBewertung:  Views:  1.655 
http://www.tools4vb.de/System:  Win2k, WinXP, Win7, Win8, Win10, Win11 Beispielprojekt 

Wie man auf einen Rechtsklick innerhalb der ListView-Elemente reagieren kann, haben wir Ihnen bereits gezeigt.

Was aber, wenn man den Rechtsklick auf einen Spaltenbezeichner abfragen will? Hierfür bietet uns das ListView-Control leider keine Möglichkeit, gezielt darauf zu reagieren. Das ListView löst lediglich beim Linksklick auf einer der Spaltenbezeichner (ColumnHeader) ein entsprechendes Event aus. Ein Rechtsklick hingegen bleibt ungeahntet.

Mit diesem Extra-Tipp zeigen wir eine Möglichkeit auf, wie man dennoch auf einen Rechtsklick reagieren kann.

Der Trick:
Der Trick besteht darin, das wir dem ListView ein Kontextmenü hinzufügen. Klickt der User nun mit der rechten Maustaste in das ListView (es spielt hierbei keine Rolle, ob der Rechtsklick im ColumnHeader-Bereich oder ListViewItem-Bereich erfolgt), wird das Opening-Event des ContextMenuStrip-Objekts ausgelöst. Durch Setzen des Parameters "Cancel" kann die Anzeige des Kontextmenüs unterdrückt werden. Jetzt müssen wir nur noch herausfinden, ob der Mausklick innerhalb der Spaltenbezeichner erfolgte.

Hierzu müssen wir zunächst das Rechteck der ColumnHeader-Leiste ermitteln. Dann brauchen wir einfach nur abzufragen, ob sich der Mauszeiger innerhalb des ermittelten Rechtecks befindet.

Das Ganze sieht wie folgt aus: Fügen Sie nachfolgende Klasse in Ihr Projekt ein.

Imports System.Runtime.InteropServices
 
Public Class lvColumnHeaderRect
  ' benötigte API-Funktionen, um das Handle der ColumnHeader zu ermitteln
  Private Delegate Function WinCallBack( _
    ByVal hWnd As IntPtr, _
    ByVal lParam As IntPtr) As Boolean
 
  <DllImport("user32.Dll")> _
  Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, _
    ByVal callBackFunc As WinCallBack, _
    ByVal lParam As IntPtr) As Integer
  End Function
 
  <DllImport("user32.dll")> _
  Private Shared Function GetWindowRect(ByVal hWnd As IntPtr, _
    ByRef lpRect As RECT) As Integer
  End Function
 
  <StructLayout(LayoutKind.Sequential)> _
  Private Structure RECT
    Public Left As Integer
    Public Top As Integer
    Public Right As Integer
    Public Bottom As Integer
  End Structure
  ' private Eigenschaften
  Private _headerRect As Rectangle = Rectangle.Empty
  Private _columns() As ColumnHeader
  ' Unsere CallBack-Funktion zum Ermitteln des Handles der ColumnHeader-Leiste
  Private Function lvCallBack(ByVal hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean
    Dim r As RECT
    If GetWindowRect(hWnd, r) <> 0 Then
      _headerRect = New Rectangle(r.Left, r.Top, r.Right - r.Left, r.Bottom - r.Top)
    End If
    Return False
  End Function
  ''' <summary>
  ''' Initialisiert die Klasse mit dem angegebenen ListView-Objekt
  ''' </summary>
  ''' <param name="ListView">ListView-Objekt</param>
  Public Sub New(ByVal ListView As ListView)
    ' Handle der ColumnHeader-Leiste ermitteln
    EnumChildWindows(ListView.Handle.ToInt32, _
      New WinCallBack(AddressOf lvCallBack), IntPtr.Zero)
 
    ' ColumnHeader-Objekte in der angezeigten Reihenfolge
    ReDim _columns(ListView.Columns.Count)
    For Each column As ColumnHeader In ListView.Columns
      _columns(column.DisplayIndex) = column
    Next
  End Sub
  ''' <summary>
  ''' Gibt das Rechteck der ColumnHeader-Leiste zurück
  ''' </summary>
  Public ReadOnly Property Rectangle() As Rectangle
    Get
      Return _headerRect
    End Get
  End Property
  ''' <summary>
  ''' Ermittelt die Spalte (das ColumnHeader-Objekt) unter dem Mauszeiger
  ''' </summary>
  ''' <param name="p">Position des Mauszeigers</param>
  ''' <value></value>
  Public ReadOnly Property ColumnHeader(ByVal p As Point) As ColumnHeader
    Get
      Dim x As Integer = _headerRect.X
      For Each column As ColumnHeader In _columns
        x += column.Width
        If p.X <= x Then
          Return column
        End If
      Next
      Return Nothing
    End Get
  End Property
End Class

So... und jetzt noch folgender Code in der Form, auf der sich das ListView befindet:

' Hilfs-Kontextmenü
Dim WithEvents lvMenu As New ContextMenuStrip
' Bei Rechtsklick will VB das Kontextmenü anzeigen
Private Sub lvMenu_Opening(ByVal sender As Object, _
  ByVal e As System.ComponentModel.CancelEventArgs) Handles lvMenu.Opening
 
  ' Anzeige des Kontextmenüs unterbinden
  e.Cancel = True
 
  ' ColumnHeader-Rechteck ermitteln
  With New lvColumnHeaderRect(ListView1)
    ' Prüfen, ob sich die Maus in der Headerzeile befindet
    If .Rectangle.Contains(Control.MousePosition) Then
      ' Rechtsklick in den ColumnHeader-Bereich
      ' ggf. Spalte ermitteln
      Dim column As ColumnHeader = .ColumnHeader(Control.MousePosition)
      If Not IsNothing(column) Then
        MsgBox("Rechtsklick auf Spalte '" & column.Text & "'")
      End If
    End If
  End With
End Sub



Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6
(einschl. Beispielprojekt!)

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
 
Copyright ©2000-2024 vb@rchiv Dieter OtterAlle Rechte vorbehalten.


Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.