다음을 통해 공유


OpenFileDlg 샘플

업데이트: 2007년 11월

이 샘플에서는 문자열을 포함하는 구조체에 대한 포인터를 필요로 하는 관리되지 않는 함수의 호출 방법을 보여 줍니다. 또한 관리되는 클래스를 사용하여 관리되지 않는 구조체를 나타내는 방법과 InAttributeOutAttribute 특성을 적용하여 클래스를 호출자로 다시 마샬링하는 방법, 그리고 클래스의 여러 가지 필드를 선언하고 초기화하여 관리되지 않는 표현을 올바르게 생성하는 방법을 보여 줍니다.

OpenFileDlg 샘플에서는 다음의 관리되지 않는 함수를 사용합니다. 이 함수는 원래의 함수 선언과 함께 표시되어 있습니다.

  • 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 클래스에는 원래 구조체의 요소가 클래스 멤버로 포함되어 있습니다. 관리되지 않는 함수에서 구조체에 대한 포인터를 필요로 할 때 클래스를 사용하는 방법을 보여 주기 위해 관리되지 않는 구조체는 관리되는 구조체 대신 클래스로 선언됩니다. 관리되는 클래스는 참조 형식이므로 이 클래스를 값으로 전달할 때는 해당 클래스에 대한 포인터가 비관리 코드에 전달됩니다. 바로 이것이 관리되지 않는 함수에서 필요로 하는 항목입니다.

클래스에는 클래스 멤버가 나타나는 순서에 따라 순차적으로 메모리에 레이아웃되도록 StructLayoutAttribute 특성이 적용됩니다. CharSet 필드는 플랫폼 호출에서 런타임에 대상 플랫폼에 따라 ANSI 및 유니코드 중 하나를 선택할 수 있도록 설정되어 있습니다.

LibWrap 클래스에는 OpenFileName 클래스를 In/Out 매개 변수를 통해 전달하는 GetOpenFileName 메서드의 관리되는 프로토타입이 포함되어 있습니다. 이 샘플에서는 OpenFileName이 In/Out 매개 변수를 통해 마샬링되고 호출자가 다시 마샬링된 변경 내용을 볼 수 있도록 InAttributeOutAttribute를 명시적으로 적용합니다. 성능상의 이유로 클래스에 대한 기본 방향 특성은 호출자가 다시 마샬링된 변경 내용을 볼 수 없도록 하는 In입니다. App클래스에서는 OpenFileName 클래스의 새 인스턴스를 만들고 Marshal.SizeOf 메서드를 사용하여 관리되지 않는 구조체의 크기를 바이트 단위로 결정합니다.

다음 코드 예제의 소스 코드는 .NET Framework Platform Invoke 기술 샘플을 통해 제공됩니다.

프로토타입 선언

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

참고 항목

작업

Platform Invoke 기술 샘플

개념

문자열 마샬링

플랫폼 호출 데이터 형식

문자열에 대한 기본 마샬링

관리 코드에서 프로토타입 만들기