Subclass a ListBox

Intercept the WM_RBUTTONDOWN message (right-click)


Imports System.Runtime.InteropServices

Public Class Form1

    Private Const GWL_WNDPROC As Integer = -4
    Private Const WM_RBUTTONDOWN As Integer = &H204

    ' Declare delegate for the new WndProc
    Private Delegate Function WndProcDelegate(hWnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr

    Private oldWndProc As IntPtr
    Private newWndProc As WndProcDelegate

    ' API declarations
    
    Private Shared Function SetWindowLongPtr(hWnd As IntPtr, nIndex As Integer, newProc As WndProcDelegate) As IntPtr
    End Function

    
    Private Shared Function SetWindowLong32(hWnd As IntPtr, nIndex As Integer, newProc As WndProcDelegate) As IntPtr
    End Function

    
    Private Shared Function CallWindowProc(lpPrevWndFunc As IntPtr,
                                           hWnd As IntPtr,
                                           Msg As Integer,
                                           wParam As IntPtr,
                                           lParam As IntPtr) As IntPtr
    End Function

    Private Function SubclassWndProc(hWnd As IntPtr,
                                     msg As Integer,
                                     wParam As IntPtr,
                                     lParam As IntPtr) As IntPtr

        If msg = WM_RBUTTONDOWN Then
            MessageBox.Show("Right-click detected on ListBox!")
        End If

        ' Call original WndProc
        Return CallWindowProc(oldWndProc, hWnd, msg, wParam, lParam)
    End Function

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ListBox1.Items.AddRange({"Item 1", "Item 2", "Item 3"})

        newWndProc = New WndProcDelegate(AddressOf SubclassWndProc)

        ' Set the new WndProc
        If IntPtr.Size = 8 Then ' 64-bit
            oldWndProc = SetWindowLongPtr(ListBox1.Handle, GWL_WNDPROC, newWndProc)
        Else ' 32-bit
            oldWndProc = SetWindowLong32(ListBox1.Handle, GWL_WNDPROC, newWndProc)
        End If
    End Sub

End Class

Download 'Subclass a ListBox.vb':

📥 Download subclass-a-listbox.vb