Die Community zu .NET und Classic VB.
Menü

VB.NET-Tipp 0029: Subclassing mit API-Funktionen

 von 

Beschreibung

Dieses Beispiel zeigt wie einfach sich "alte" VB6-Codes nach VB.net portieren lassen, obwohl dies nicht immer so ist. Es muss allerdings angemerkt werden, dass das .NET-Framework über die WndProc-Funktion einer Form ein wesentlich flexibleres Mittel für Subclassing bietet.

Für neuere Framework-Versionen empfehlen wir die Verwendung von Subclassing mit .NET-Bordmitteln [Tipp 0028].

Schwierigkeitsgrad:

Schwierigkeitsgrad 2

Framework-Version(en):

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

.NET-Version(en):

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

Download:

Download des Beispielprojektes [3,56 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!

' Projektversion:   Visual Studio 2002/2003
' Option Strict:    An
' Option Explicit:  An
'
' Referenzen: 
'  - System
'  - System.Drawing
'  - System.Windows.Forms
'

' ##############################################################################
' ################################ MainForm.vb #################################
' ##############################################################################
Option Explicit On 
Option Strict On
Option Compare Binary

Imports System
Imports System.Windows.Forms

' <remarks>
'   Hauptformular der Anwendung.
' </remarks>
Public Class MainForm
    Inherits System.Windows.Forms.Form

#Region " Delegat-Deklarationen "
    Private Delegate Function SubWndProcDelegate( _
        ByVal hWnd As IntPtr, _
        ByVal msg As Int32, _
        ByVal wParam As Int32, _
        ByVal lParam As Int32) As Int32
#End Region

#Region " API-Deklarationen "

    ' Um die Möglichkeit offen zu lassen, auch einen "echten" Funktionszeiger 
    ' in Form einer Variablen vom Typ IntPtr an das API zu übergeben, wird der 
    ' Name SetWindowLong überladen.
    Private Declare Function SetWindowLong _
        Lib "user32.dll" Alias "SetWindowLongA" ( _
            ByVal hWnd As IntPtr, _
            ByVal nIndex As Int32, _
            ByVal dwNewLong As IntPtr) As Int32
    Private Declare Function SetWindowLong _
        Lib "user32.dll" Alias "SetWindowLongA" ( _
            ByVal hWnd As IntPtr, _
            ByVal nIndex As Int32, _
            ByVal dwNewLong As SubWndProcDelegate) As IntPtr

    Private Declare Function CallWindowProc _
        Lib "user32.dll" Alias "CallWindowProcA" ( _
            ByVal lpPrevWndFunc As IntPtr, _
            ByVal hWnd As IntPtr, _
            ByVal msg As Int32, _
            ByVal wParam As Int32, _
            ByVal lParam As Int32) As Int32

    Private Const GWL_WNDPROC As Int32 = -&H4

    Private Const WM_NCLBUTTONDBLCLK As Int32 = &HA3
    Private Const WM_NCLBUTTONDOWN As Int32 = &HA1
    Private Const WM_NCLBUTTONUP As Int32 = &HA2
#End Region

    Private m_intptrPrevWndProc As IntPtr


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

        ' Subclassing starten.
        InitializeSubclassing(Me.Handle)
    End Sub

    ' <summary>
    '   Initialisieren des Subclassing.
    ' </summary>
    ' <param name="hWnd">Handle des zu 
    '   subclassenden Fensters.</param>
    Public Sub InitializeSubclassing( _
      ByVal hWnd As IntPtr)
        m_intptrPrevWndProc = SetWindowLong( _
          hWnd, _
          GWL_WNDPROC, _
          AddressOf SubWndProc)
    End Sub

    ' <summary>
    '   Beenden des Subclassing durch 
    '   Zurücksetzen des Funktionszeigers 
    '   auf die echte Fensterprozedur.
    ' </summary>
    ' <param name="hWnd">Handle des Fensters, 
    '   dessen Subclassing entfernt werden soll.</param>
    Public Sub TerminateSubclassing( _
      ByVal hWnd As IntPtr)
        SetWindowLong(hWnd, _
          GWL_WNDPROC, _
          m_intptrPrevWndProc)
    End Sub

    ' <summary>
    '   Unsere Fensterprozedur, hier wird die 
    '   Doppelklick-Meldung auf dem Non-Client-Bereich
    '   des Formulars angefangen.
    ' </summary>
    ' <param name="hWnd">Siehe Dokumentation zum Platform SDK.</param>
    ' <param name="msg">Siehe Dokumentation zum Platform SDK.</param>
    ' <param name="wParam">Siehe Dokumentation zum Platform SDK.</param>
    ' <param name="lParam">Siehe Dokumentation zum Platform SDK.</param>
    ' <returns>Siehe Dokumentation zum Platform SDK.</returns>
    Private Function SubWndProc( _
      ByVal hWnd As IntPtr, _
      ByVal msg As Int32, _
      ByVal wParam As Int32, _
      ByVal lParam As Int32) As Int32

        ' Die Meldung besagt, dass der 
        ' Non-Client-Bereich des Formulars doppelt
        ' angeklickt wurde.
        If msg = WM_NCLBUTTONDBLCLK Then
            MessageBox.Show( _
              "Der Non-Client-Bereich wurde doppelt angeklickt.", _
              "SubWndProc")

            ' Wenn der Benutzer will, dass die Meldung 
            ' unterdrückt wird, dann steigen
            ' wir hier aus, ohne sie an Windows weiterzugeben.
            If chkNoWindowStateChange.Checked Then
                Return 0
            End If
        End If

        ' Weiterreichen der Messages an Windows. 
        ' Hier besteht auch die Möglichkeit,
        ' Meldungen zu unterdrücken, indem man 
        ' sie nicht weiterleitet.
        Return CallWindowProc(m_intptrPrevWndProc, hWnd, msg, wParam, lParam)
    End Function
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.

Archivierte Nutzerkommentare 

Klicken Sie diesen Text an, wenn Sie die 1 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.

Kommentar von David Ewelt am 17.01.2005 um 23:31

Hallo,

leider muss ich Melden das dieser Tipp (beim mir) nicht funktioniert.
Die Meldungen werden zwar erfolgreich abgefangen und wieder weitergesendet, aber wenn man sich ewtas länger mit der Maus auf dem Formular bewegt wird manchmal ein "Runtime.InteropServices.SEHException" Fehler ausgelößt der Angibt das die externe Komponente einen Fehler auslößte oder das Programm beendet sich ganz still von alleine.
Ich benutze Windows 2000 mit SP4.

Mfg
David Ewelt