如何调用需要指向包含字符串的结构的指针的非托管函数

http://msdn.microsoft.com/zh-cn/windows/hardware/w5tyztk9(v=vs.71)

OpenFileDlg 示例

该示例演示如何调用需要指向包含字符串的结构的指针的非托管函数。 此外,它还演示如何使用托管类来表示非托管结构,如何应用 InAttribute 和 OutAttribute 特性将该类封送回调用方,以及如何声明并初始化该类的不同字段以产生正确的非托管表示形式。

OpenFileDlg 示例使用以下非托管函数(这里同时显示其原始函数声明):

  • 从 Comdlg32.dll 导出的 GetOpenFileName

    BOOL GetOpenFileName(LPOPENFILENAME lpofn);

传递给上一函数的 LPOPENFILENAME 结构(来自 Win32 API)包含以下元素:

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 和 Unicode 格式之间进行选择。

LibWrap类包含GetOpenFileName方法的托管原型,该方法将OpenFileName类作为 In/Out 参数传递。 通过显式应用 InAttribute 和 OutAttribute,该示例确保将OpenFileName作为 In/Out 参数进行封送处理并且调用方可以查看封送回的更改。(为了提高性能,类的默认 方向特性为 In,以防止调用方查看封送回的更改。)App类创建OpenFileName类的一个新实例,并使用 MarshalSizeOf 方法确定非托管结构的大小(以字节为单位)。

声明原型

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

调用函数

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

typedef struct tagOFN { /* ofn */
  DWORD lStructSize;
  HWND hwndOwner;
  HINSTANCE hInstance;
  LPCSTR lpstrFilter;
  LPSTR lpstrCustomFilter;
  DWORD nMaxCustFilter;
  DWORD nFilterIndex;
  LPSTR lpstrFile;
  DWORD nMaxFile;
  LPSTR lpstrFileTitle;
  DWORD nMaxFileTitle;
  LPSTR lpstrInitialDir;
  LPCSTR lpstrTitle;
  DWORD Flags;
  WORD nFileOffset;
  WORD nFileExtension;
  LPCSTR lpstrDefExt;
  DWORD lCustData;
  LPOFNHOOKPROC lpfnHook;
  LPCSTR lpTemplateName;
} OPENFILENAME;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值