共用方式為


OpenFileDlg 範例

更新:2007 年 11 月

這個範例示範如何呼叫 Unmanaged 函式,其預期含有字串之結構的指標。此外,它也示範如何使用 Managed 類別來表示 Unmanaged 結構、如何套用 InAttributeOutAttribute 屬性來封送處理類別回呼叫端,以及如何宣告和初始化類別的不同欄位來產生正確的 Unmanaged 表示。

OpenFileDlg 範例使用下列 Unmanaged 函式,顯示其原始函式宣告:

  • 從 Comdlg32.dll 匯出 GetOpenFileName

    BOOL GetOpenFileName(LPOPENFILENAME lpofn);
    

傳遞至前一個函式之 Win32 API 的 LPOPENFILENAME 結構包含下列項目:

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

在這個範例中,OpenFileName 類別包含原始結構的元素做為類別成員。Unmanaged 結構是宣告為類別而非 Managed 結構,來顯示當 Unmanaged 函式預期結構的指標時,類別如何使用類別。因為 Managed 類別是參考型別 (Reference Type),當它是以傳值方式傳遞時,類別的指標會被傳遞至 Unmanaged 程式碼。這正是 Unmanaged 函式所預期的。

套用 StructLayoutAttribute 屬性以確保成員是按照出現的順序,循序配置於記憶體中。設定 CharSet 欄位,以便平台叫用可以根據目標平台在 Run Time 於 ANSI 和 Unicode 格式間選擇。

LibWrap 類別包含 GetOpenFileName 方法的 Managed 原型,會將 OpenFileName 類別當成 In/Out 參數傳遞。在這個範例中,透過明確套用 InAttributeOutAttribute,可以確保將 OpenFileName 封送處理為 In/Out 參數,而呼叫端可以查看封送處理回的變更 (由於效能因素,類別的預設方向屬性是 In,避免呼叫端查看封送處理回的變更)。App 類別會建立 OpenFileName 類別的新執行個體,並使用 Marshal.SizeOf 方法決定 Unmanaged 結構的大小 (以位元組為單位)。

下列程式碼範例的原始程式碼是由 .NET Framework 平台叫用技術範例所提供。

宣告原型

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

呼叫函式

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

請參閱

工作

平台叫用技術範例

概念

封送處理字串

平台叫用資料型別

字串的預設封送處理

在 Managed 程式碼中建立原型