Sdílet prostřednictvím


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

Marshallen von Zeichenfolgen

Datentypen für den Plattformaufruf

Standardmäßiges Marshalling für Zeichenfolgen

Erstellen von Prototypen in verwaltetem Code