Closed. This question needs to be more focused. It is not currently accepting answers. Learn more。
想改进这个问题吗?更新问题,使其只关注一个问题editing this post。
三年前关闭。
我不得不将一个20年前用C编写的程序“翻译”到VB.net上,因为它的旧SQL连接风格已经不兼容了。但是,我对C的经验很少,对winAPI(C应用程序使用的)的经验更少。。。我想知道,在VB.net中是否可以使用API中的相同函数?
我可以添加这样的声明:
获取窗口句柄IntPtr(在vb.net中)。然而,C程序使用的功能包括:
通过导入user32.dll,我无法获得hWnd句柄,但我可以获得IntPtr(如果我理解的很好,是一个指向窗口的整数点,对吧?有点像hWnd-->我可能完全错了,但这就是我所理解的)
当我进入每种类型的定义(例如:NEAR、HINSTANCE、LPCSTR等等)时,我试图在VB中找到一个等价的调用,但是。。。没用。举个例子,我在看附近,我想是为了判断两个指针是否在内存中很接近?(可能又错了,这正是我收集到的)。
最后,我的问题是,这样的呼叫是否存在于VB.NET中?甚至更适用于更现代的框架,等等?
正如我上面所说的,
我们已经看到了
要封送指向
然后,您需要在代码中的某个位置创建一个具有相同签名的函数,以接收来自本机代码的调用。类似于:
然后,可以添加类成员来保存该委托:
在所有这些之后,您终于可以导入
我们现在可以从代码中调用函数:
关于函数调用的两个注意事项:
如果你能做到这一点,恭喜你!代码中可能有几个bug,但这应该可以让您继续。对于其他Windows API类型,您可以在pinvoke.net上找到很多信息。
如果您有很多互操作性,那么只需在项目中添加C++/CLI DLL就更容易,并在本地调用这些函数。它简单得多,你可以定义你想要的函数。此外,C++/CLI与任何.NET语言都有作用。
想改进这个问题吗?更新问题,使其只关注一个问题editing this post。
三年前关闭。
我不得不将一个20年前用C编写的程序“翻译”到VB.net上,因为它的旧SQL连接风格已经不兼容了。但是,我对C的经验很少,对winAPI(C应用程序使用的)的经验更少。。。我想知道,在VB.net中是否可以使用API中的相同函数?
我可以添加这样的声明:
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function SetWindowText(hWnd As IntPtr, lpString As String) As Boolean
End Function
获取窗口句柄IntPtr(在vb.net中)。然而,C程序使用的功能包括:
BOOL NEAR GoModal( HINSTANCE hInstance, LPCSTR lpszTemplate,HWND hWnd, DLGPROC lpDlgProc, LPARAM lParam )
通过导入user32.dll,我无法获得hWnd句柄,但我可以获得IntPtr(如果我理解的很好,是一个指向窗口的整数点,对吧?有点像hWnd-->我可能完全错了,但这就是我所理解的)
当我进入每种类型的定义(例如:NEAR、HINSTANCE、LPCSTR等等)时,我试图在VB中找到一个等价的调用,但是。。。没用。举个例子,我在看附近,我想是为了判断两个指针是否在内存中很接近?(可能又错了,这正是我收集到的)。
最后,我的问题是,这样的呼叫是否存在于VB.NET中?甚至更适用于更现代的框架,等等?
最佳答案
让我们分解函数调用中的参数:
BOOL NEAR GoModal(HINSTANCE hInstance,
LPCSTR lpszTemplate,
HWND hWnd,
DLGPROC lpDlgProc,
LPARAM lParam )
BOOL
是32位整数。您可以在代码中使用System.Boolean
类型,但它需要对其应用MarshalAsAttribute
,将类型指定为UnmanagedType.Bool
NEAR
指定编译器的信息。当转换为.net时,可以忽略它。HINSTANCE
是aHandle
到aInstance
。转换为.net时,句柄通常定义为IntPtr
值。这并不意味着它是指向内存的指针。(即-Marshal.Read
不能使用。)LPCSTR
是一种Long
Pointer
到C
样式的。这是一个STR
字符串,因此它意味着参数需要ANSI
和MarshalAsAttribute
一起使用。如果这是一个out参数,事情会更复杂,您需要传递一个UnmanagedType.LPStr
或使用StringBuilder
/Marshal.AllocHGlobal
来分配非托管内存。Marshal.AllocCoTaskMem
是aHWND
到aHandle
的。像Window
一样,它通常被封送为HINSTANCE
IntPtr
有点复杂,所以我将在下面讨论它。DLGPROC
是一个LPARAM
Long
。Microsoft在创建Parameter
类时用于此类型的标准实现是Message
。你应该效仿。正如我上面所说的,
IntPtr
更复杂。它实际上是指向函数的指针(引用)。特别是有签名的:INT_PTR CALLBACK DialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
我们已经看到了
DLGPROC
和HWND
,所以让我们快速查看这个签名中的其他内容。LPARAM
是一个INT_PTR
Integer
。如果听起来很熟悉的话,那应该是。它只是一个Pointer
。IntPtr
是编译器用来确定函数应该如何编译,以及使用它的人应该如何向函数发送参数的另一位信息。默认情况下,.net封送处理程序会处理此问题,因此不需要额外的配置。CALLBACK
代表WPARAM
Word
。在本例中,这是一个旧术语,您需要使用Param
来接收值。要封送指向
IntPtr
的指针,您需要创建具有适当签名的委托:Delegate Function DLGPROC(ByVal hWnd As IntPtr,
ByVal uMsg As UInt32,
ByVal wParam As IntPtr,
ByVal lParam As IntPtr) As IntPtr
然后,您需要在代码中的某个位置创建一个具有相同签名的函数,以接收来自本机代码的调用。类似于:
Private Function MyDialogProc(ByVal hWnd As IntPtr,
ByVal uMsg As UInt32,
ByVal wParam As IntPtr,
ByVal lParam As IntPtr) As IntPtr
Return IntPtr.Zero ' Put the appropriate code here.
End Function
然后,可以添加类成员来保存该委托:
Private DialogProc As DLGPROC = New DLGPROC(AddressOf Me.MyDialogProc)
在所有这些之后,您终于可以导入
DLGPROC
函数原型了。(耶!)看起来像是:<DllImport("DLL_NAME")>
Private Shared Function GoModal(ByVal hInstance As IntPtr,
<MarshalAs(UnmanagedType.LPStr)> ByVal lpszTemplate As String,
ByVal hWnd As IntPtr,
ByVal lpDlgProc As IntPtr, ' More on this below
ByVal lParam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
我们现在可以从代码中调用函数:
Dim dialogProcedure As IntPtr = Marshal.GetFunctionPointerForDelegate(Me.DialogProc)
Dim result As Boolean = GoModal(IntPtr.Zero,
"Template",
Me.Handle,
dialogProcedure,
New IntPtr(100))
关于函数调用的两个注意事项:
GoModal
与IntPtr.Zero
相同NULL
创建具有指定值的New IntPtr(100)
。(有时IntPtr
只是一个数字)如果你能做到这一点,恭喜你!代码中可能有几个bug,但这应该可以让您继续。对于其他Windows API类型,您可以在pinvoke.net上找到很多信息。
如果您有很多互操作性,那么只需在项目中添加C++/CLI DLL就更容易,并在本地调用这些函数。它简单得多,你可以定义你想要的函数。此外,C++/CLI与任何.NET语言都有作用。
关于c - 在vb.net中调用winAPI函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37616203/