Condividi tramite


Esempio di OpenFileDlg

Aggiornamento: novembre 2007

In questo esempio viene dimostrato come chiamare una funzione non gestita per la quale è previsto un puntatore a una struttura contenente una stringa. Viene inoltre dimostrato come utilizzare una classe gestita per rappresentare una struttura non gestita, come applicare gli attributi InAttribute e OutAttribute per effettuare nuovamente il marshalling della classe nel chiamante e come dichiarare e inizializzare campi diversi della classe per produrre la rappresentazione non gestita corretta.

Nell'esempio di OpenFileDlg viene utilizzata la seguente funzione non gestita, illustrata con la dichiarazione di funzione originale:

  • GetOpenFileName esportata da Comdlg32.dll.

    BOOL GetOpenFileName(LPOPENFILENAME lpofn);
    

La struttura LPOPENFILENAME dall'API Win32, che viene passata alla funzione precedente, contiene i seguenti elementi:

typedef struct tagOFN { 
  DWORD         lStructSize; 
  //…
  LPCTSTR       lpstrFilter; 
  //…
  LPTSTR        lpstrFile; 
  DWORD         nMaxFile; 
  LPTSTR        lpstrFileTitle; 
  DWORD         nMaxFileTitle; 
  LPCTSTR       lpstrInitialDir; 
  LPCTSTR       lpstrTitle; 
  //… 
  LPCTSTR       lpstrDefExt; 
  //…
} OPENFILENAME, *LPOPENFILENAME; 

In questo esempio, nella classe OpenFileName sono contenuti gli elementi della struttura originale come membri di classe. La struttura non gestita viene dichiarata come classe, invece che come struttura gestita, per illustrare come sia possibile utilizzare una classe quando per la funzione non gestita è previsto un puntatore a una struttura. Poiché una classe gestita è un tipo di riferimento, quando viene passata per valore, un puntatore alla classe viene passato al codice non gestito. Questa situazione è esattamente quella prevista dalla funzione non gestita.

L'attributo StructLayoutAttribute viene applicato alla classe per fare in modo che i membri vengano disposti in sequenza nella memoria, nell'ordine in cui appaiono. Il campo CharSet viene impostato in modo che nel richiamo piattaforma possa essere effettuata la scelta tra i formati ANSI e Unicode in fase di esecuzione, in base al sistema operativo di destinazione.

La classe LibWrap contiene il prototipo gestito del metodo GetOpenFileName, che passa la classe OpenFileName come parametro in/out. Con l'applicazione esplicita di InAttribute e OutAttribute, nell'esempio sono garantiti il marshalling di OpenFileName come parametro in/out e la visualizzazione da parte del chiamante delle modifiche restituite con il marshalling. Per questioni di prestazioni, l'attributo direzionale predefinito per una classe è In, condizione che impedisce al chiamante di vedere le modifiche restituite con il marshalling. La classe App consente di creare una nuova istanza della classe OpenFileName e il metodo Marshal.SizeOf viene utilizzato per determinare la dimensione in byte della struttura non gestita.

Il codice sorgente per gli esempi di codice riportati di seguito è fornito dall'Esempio di tecnologia di richiamo piattaforma di .NET Framework.

Dichiarazione dei prototipi

' 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 );  
}

Chiamata delle funzioni

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 );
      }
   }
}

Vedere anche

Attività

Esempio di tecnologia di richiamo piattaforma

Concetti

Marshalling di stringhe

Tipi di dati del richiamo piattaforma

Marshalling predefinito per le stringhe

Creazione di prototipi nel codice gestito