Die Community zu .NET und Classic VB.
Menü

FAQ 0153: Wie verwende ich Win32-API-Funktionen in VB.NET?

 von 

Frage 

Wie verwende ich Funktionen der Win32-API in meiner .NET-Anwendung?

Antwort  

Das .NET Framework ist zwar riesig, deckt aber trotzdem nicht alle Funktionen ab; insbesondere fehlen Umsetzungen so mancher Win32-API-Funktion.

Ein praktisches Beispiel ist die HotKey-API-Funktion. Mit ihr lassen sich globale Tastenkombinationen, sog. HotKeys, registrieren, um diese überall "abzufangen" und ein entsprechendes Ereignis auszulösen resp. Programmcode zu starten.
In VB Classic wurden die dafür benötigten API-Funktionen wie folgt deklariert:

Private Declare Function RegisterHotKey Lib "user32" ( _
                ByVal hWnd As Long, _
                ByVal ID As Long, _
                ByVal fsModifiers As Long, _
                ByVal vk As Long) As Long

Listing 1: Eine HotKey-API-Funktion in VB Classic

In VB.NET ist die Deklaration unbedingt abzuändern, da es sonst zum Programmabsturz kommen kann:

Private Declare Function RegisterHotKey Lib "user32" ( _
                ByVal Hwnd As IntPtr, _
                ByVal ID As Integer, _
                ByVal Modifiers As Integer, _
                ByVal Key As Integer) As Integer

Listing 2: Die gleiche HotKey-API-Funktion in VB.NET

Alle Long-Datentypen sind in Integer zu ändern, denn während in VB Clasic ein Integer 16, ein Long dagegen 32 Bit breit war, sind es in VB.NET 32 und 64 Bits.
Eine weitere Besonderheit ist beim hWnd-Parameter zu beachten, der von Long in IntPtr geändert wurde. IntPtr ist eine einfache Struktur, in der 32- oder 64-Bit-Werte gespeichert werden; sie wird in VB.NET für sog. Handles verwendet.

In VB.Net kann man einer API-Funktion - oder auch einer (unmanaged) DLL-Deklaration - noch einige Parameter für den Aufruf einer DLL vom Framework angegeben werden. Dann sieht eine Deklaration wie eine ganz normale Funktion aus (der Namensraum "System.Runtime.InteropServices" muss vorher importiert werden):

<DllImport("user32.dll")> _
Public Shared Function RegisterHotKey( _
                ByVal Hwnd As IntPtr, _
                ByVal ID As Integer, _
                ByVal Modifiers As Integer, _
                ByVal Key As Integer) As Integer
End Function

Listing 3: Die gleiche HotKey-API-Funktion in VB.NET

Die zusätzliche Funktion, "DllImport", erhält bis zu acht optionale Parameter.
Hier ein Beispiel für den Aufruf mit zwei Parametern:

<DllImport("custom.dll", EntryPoint:="Einstiegspunkt", CharSet:=CharSet.Auto)> _
Public Shared Function MeineFunktion( _
                ByVal Param1 As Integer)
End Function

Listing 4: Deklaration mit weiteren Angaben

Der Paramter "EntryPoint" bestimmt einen alternativen Einstiegspunkt. In VB Classic enthielt die Deklaration anstelle dessen einen Alias-Eintrag.
Mit dem Paramter "CharSet" wird festgelegt, mit welchem Zeichensatz Zeichenketten 'gemarshallt' werden sollen.

Die anderen sechs Parameter lauten:

  • BestFitMapping(Boolean)
  • CallingConvention(CallingConvention)
  • ExactSpelling(Boolean)
  • PreserveSig(Boolean)
  • SetLastError(Boolean)
  • ThrowOnUnmappableChar(Boolean)

Für weitere Informationen und Beschreibungen siehe die MSDN Library sowie unter pinvoke.net.

Sie können API-Funktionen entweder im VB Classic Stil oder - wie dargestellt - mit angepassten Datentypen im .NET-Stil deklarieren.

Welche Funktionen vom .NET-Framework abgedeckt werden, kann man hier nachschlagen: Microsoft Win32 to Microsoft .NET Framework API Map.
Jedoch sollte man nicht blind darauf vertrauen, daß Microsoft diese Funktionen korrekt implementiert hat. So kann man statt GetDIBits laut der genannten Liste die Funktion System.Drawing.Bitmap.LockBits verwenden. Diese enthält jedoch zahlreiche Bugs, so ist es beispielsweise nicht möglich, eine 24bpp-Bitmap in ein Monochrom-Bitmap zu konvertieren.
Folgender Code soll einen der Bugs demonstrieren:

Private Sub Test()

    Dim bmp As New Bitmap(100, 100, PixelFormat.Format24bppRgb)

    ' "System.ArgumentException" ist in System.Drawing.dll aufgetreten

    'Ungültiger Parameter. (Format1bppIndexed)
    Dim BmpData As BitmapData = bmp.LockBits( _
        New Rectangle(0, 0, bmp.Width, bmp.Height), _
        Imaging.ImageLockMode.ReadOnly, _
        Imaging.PixelFormat.Format1bppIndexed)

    bmp.UnlockBits(BmpData)

    bmp.Dispose()

End Sub

Listing 5: Demo: Bug in LockBits

In diesem Fall bleibt einem nichts anderes übrig, als direkt auf die Funktionen der Win32-API zuzugreifen.

Ihre Meinung  

Falls Sie Fragen zu dieser FAQ haben, Ihre Erfahrung mit anderen Nutzern austauschen möchten oder auf eine Ergänzung hinweisen 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.