Imports System.Runtime.InteropServices
Public Class ClassClipboardWatcher
    Inherits NativeWindow
    Implements IDisposable

    Private Class Win32
        <DllImport("user32", EntryPoint:="SetClipboardViewer")>
        Public Shared Function SetClipboardViewer(ByVal hWnd As IntPtr) As IntPtr
        End Function
    End Class

    Const WM_DRAWCLIPBOARD As Integer = &H308

    Public Event ClipboardChanged As EventHandler(Of IDataObject)
    Public Shared Singleton As New ClassClipboardWatcher

    Private _handle As IntPtr

    Private Sub New()
        MyBase.CreateHandle(New CreateParams)
        _handle = Win32.SetClipboardViewer(Handle)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)

        Select Case m.Msg
            Case WM_DRAWCLIPBOARD
                Dim oData As IDataObject = Clipboard.GetDataObject
                RaiseEvent ClipboardChanged(Me, oData)
        End Select
        MyBase.WndProc(m)
    End Sub

#Region "IDisposable Support"
    ' Für diese Klasse ist korrekte Ressourcenbereinigung besonders wichtig, da 
    ' mit systemübergreifenden Ressourcen gearbeitet wird

    ' So ermitteln Sie überflüssige Aufrufe
    Private disposedValue As Boolean = False

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not disposedValue Then
            If disposing Then
                ' TODO: Verwaltete Ressourcen freigeben, wenn sie explizit 
                ' aufgerufen werden
            End If
            MyBase.DestroyHandle()
            Dim H As IntPtr = Win32.SetClipboardViewer(_handle)
        End If
        disposedValue = True
    End Sub

    ' Dieser Code wird von Visual Basic hinzugefügt, um das Dispose-Muster 
    ' richtig zu implementieren.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Sie sollten diesen Code nicht ändern, sondern stattdessen ihren
        ' Bereinigungscode oben in 
        ' Dispose(ByVal disposing As Boolean) einfügen.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

    Protected Overrides Sub Finalize()
        MyBase.Finalize()
        Dispose(False)
    End Sub
#End Region
End Class
