OpenFileDlg-Beispiel
Aktualisiert: November 2007
Dieses Beispiel demonstriert, wie eine nicht verwaltete Funktion aufgerufen wird, die einen Zeiger auf eine Struktur erwartet, die eine Zeichenfolge enthält. Darüber hinaus wird demonstriert, wie eine verwaltete Klasse zum Darstellen einer nicht verwalteten Struktur verwendet wird, wie das InAttribute-Attribut und das OutAttribute-Attribut zum Zurückmarshallen der Klasse an den Aufrufer angewendet wird und wie verschiedene Felder der Klasse zum Erzeugen der richtigen nicht verwalteten Darstellung deklariert und initialisiert werden.
Das OpenFileDlg-Beispiel verwendet die folgende nicht verwaltete Funktion, die zusammen mit ihrer ursprünglichen Funktionsdeklaration aufgeführt wird:
GetOpenFileName aus Comdlg32.dll exportiert.
BOOL GetOpenFileName(LPOPENFILENAME lpofn);
Die LPOPENFILENAME-Struktur aus der Win32-API, die an die vorherige Funktion übergeben wird, enthält die folgenden Elemente:
typedef struct tagOFN {
DWORD lStructSize;
//…
LPCTSTR lpstrFilter;
//…
LPTSTR lpstrFile;
DWORD nMaxFile;
LPTSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCTSTR lpstrInitialDir;
LPCTSTR lpstrTitle;
//…
LPCTSTR lpstrDefExt;
//…
} OPENFILENAME, *LPOPENFILENAME;
In diesem Beispiel enthält die OpenFileName-Klasse die Elemente der Originalstruktur als Klassenelemente. Die nicht verwaltete Struktur wird nicht als verwaltete Struktur, sondern als Klasse deklariert, um zu zeigen, wie eine Klasse verwendet werden kann, wenn die nicht verwaltete Funktion einen Zeiger auf eine Struktur erwartet. Da eine nicht verwaltete Klasse ein Referenztyp ist, wird ein Zeiger auf die Klasse an den nicht verwalteten Code übergeben, wenn diese durch einen Wert übergeben wird. Genau das erwartet die nicht verwaltete Funktion.
Das StructLayoutAttribute-Attribut wird auf die Klasse angewendet, um sicherzustellen, dass die Member im Speicher sequenziell in der Reihenfolge ihres Auftretens angeordnet werden. Das CharSet-Feld wird so eingerichtet, dass Plattformaufruf zur Laufzeit basierend auf der Zielplattform zwischen den Formaten ANSI und Unicode wählen kann.
Die LibWrap-Klasse enthält den verwalteten Prototyp der GetOpenFileName-Methode, der die OpenFileName-Klasse als In/Out-Parameter übergibt. Indem InAttribute und OutAttribute explizit angewendet werden, stellt das Beispiel sicher, dass OpenFileName als In/Out-Parameter gemarshallt wird und der Aufrufer die zurückgemarshallten Änderungen sehen kann. (Aus Leistungsgründen ist das direktionale Attribut für eine Klasse In, sodass der Aufrufer die zurückgemarshallten Änderungen nicht sehen kann.) Die App-Klasse erstellt eine neue Instanz der OpenFileName-Klasse und verwendet die Marshal.SizeOf-Methode, um die Größe der nicht verwalteten Struktur in Bytes anzugeben.
Der Quellcode für die folgenden Codebeispiele wird im Technologiebeispiel für Plattformaufrufe in .NET Framework bereitgestellt.
Deklarieren von Prototypen
' Declare a class member for each structure element.
< StructLayout( LayoutKind.Sequential, CharSet:=CharSet.Auto )> _
Public Class OpenFileName
Public structSize As Integer = 0
'…
Public filter As String = Nothing
'…
Public file As String = Nothing
Public maxFile As Integer = 0
Public fileTitle As String = Nothing
Public maxFileTitle As Integer = 0
Public initialDir As String = Nothing
Public title As String = Nothing
'…
Public defExt As String = Nothing
'…
End Class 'OpenFileName
Public Class LibWrap
' Declare managed prototype for the unmanaged function.
Declare Auto Function GetOpenFileName Lib "Comdlg32.dll" ( _
<[In], Out> ByVal ofn As OpenFileName ) As Boolean
End Class 'LibWrap
// Declare a class member for each structure element.
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Auto )]
public class OpenFileName
{
public int structSize = 0;
//…
public String filter = null;
//…
public String file = null;
public int maxFile = 0;
public String fileTitle = null;
public int maxFileTitle = 0;
public String initialDir = null;
public String title = null;
//…
public String defExt = null;
//…
}
public class LibWrap
{
// Declare a managed prototype for the unmanaged function.
[ DllImport( "Comdlg32.dll", CharSet=CharSet.Auto )]
public static extern bool GetOpenFileName([ In, Out ]
OpenFileName ofn );
}
Aufrufen von Funktionen
Public Class App
Public Shared Sub Main()
Dim ofn As New OpenFileName()
ofn.structSize = Marshal.SizeOf( ofn )
ofn.filter = "Log files" & ChrW(0) & "*.log" & ChrW(0) & _
"Batch files" & ChrW(0) & "*.bat" & ChrW(0)
ofn.file = New String( New Char( 256 ) {})
ofn.maxFile = ofn.file.Length
ofn.fileTitle = New String( New Char( 64 ) {})
ofn.maxFileTitle = ofn.fileTitle.Length
ofn.initialDir = "C:\"
ofn.title = "Open file called using platform invoke..."
ofn.defExt = "txt"
If LibWrap.GetOpenFileName( ofn ) Then
Console.WriteLine( "Selected file with full path: {0}", _
ofn.file )
End If
End Sub 'Main
End Class 'OpenFileDlgSample
public class App
{
public static void Main()
{
OpenFileName ofn = new OpenFileName();
ofn.structSize = Marshal.SizeOf( ofn );
ofn.filter = "Log files\0*.log\0Batch files\0*.bat\0";
ofn.file = new String( new char[ 256 ]);
ofn.maxFile = ofn.file.Length;
ofn.fileTitle = new String( new char[ 64 ]);
ofn.maxFileTitle = ofn.fileTitle.Length;
ofn.initialDir = "C:\\";
ofn.title = "Open file called using platform invoke...";
ofn.defExt = "txt";
if( LibWrap.GetOpenFileName( ofn ))
{
Console.WriteLine( "Selected file with full path: {0}",
ofn.file );
}
}
}
Siehe auch
Aufgaben
Technologiebeispiel für Plattformaufrufe
Konzepte
Datentypen für den Plattformaufruf