Freigeben über


OpenFileDlg-Beispiel

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.

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 hwnd As IntPtr = IntPtr.Zero
    Public hinst As IntPtr = IntPtr.Zero
    Public filter As String = Nothing
    Public custFilter As String = Nothing
    Public custFilterMax As Integer = 0
    Public filterIndex As Integer = 0
    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 flags As Integer = 0
    Public fileOffset As Short = 0
    Public fileExtMax As Short = 0
    Public defExt as String = Nothing
    Public custData As Integer = 0
    Public pHook As IntPtr = IntPtr.Zero
    Public template As String = Nothing
End Class

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
// Declare a class member for each structure element.
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public class OpenFileName
{
    public int       structSize = 0;
    public IntPtr    hwnd = IntPtr.Zero;
    public IntPtr    hinst = IntPtr.Zero;
    public string    filter = null;
    public string    custFilter = null;
    public int       custFilterMax = 0;
    public int       filterIndex = 0;
    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 int       flags = 0;
    public short     fileOffset = 0;
    public short     fileExtMax = 0;
    public string    defExt = null;
    public int       custData = 0;
    public IntPtr    pHook = IntPtr.Zero;
    public string    template = 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);
}
// Declare a class member for each structure element.
[StructLayout(LayoutKind::Sequential, CharSet=CharSet::Auto)]
public ref class OpenFileName
{
public:
    int       structSize;
    IntPtr    hwnd;
    IntPtr    hinst;
    String^   filter;
    String^   custFilter;
    int       custFilterMax;
    int       filterIndex;
    String^   file;
    int       maxFile;
    String^   fileTitle;
    int       maxFileTitle;
    String^   initialDir;
    String^   title;
    int       flags;
    short     fileOffset;
    short     fileExtMax;
    String^   defExt;
    int       custData;
    IntPtr    pHook;
    String^   tmplate;

    OpenFileName()
    {
        // Initialize the fields.
        for each (FieldInfo^ fi in this->GetType()->GetFields())
        {
            fi->SetValue(this, nullptr);
        }
    }
};

public ref class LibWrap
{
public:
    // Declare a managed prototype for the unmanaged function.
    [DllImport("Comdlg32.dll", CharSet=CharSet::Auto)]
    static 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
End Class
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);
        }
    }
}
public ref class App
{
public:
    static void Main()
    {
        OpenFileName^ ofn = gcnew OpenFileName();

        ofn->structSize = Marshal::SizeOf(ofn);
        ofn->filter = "Log files\0*.log\0Batch files\0*.bat\0";
        ofn->file = gcnew String(gcnew array<Char>(256));
        ofn->maxFile = ofn->file->Length;
        ofn->fileTitle = gcnew String(gcnew array<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

Konzepte

Marshallen von Zeichenfolgen

Datentypen für den Plattformaufruf

Standardmäßiges Marshalling für Zeichenfolgen

Weitere Ressourcen

Creating Prototypes in Managed Code