如何在 VBA 中声明 PtrSafe Sub? Windows 7,Excel 2016,64 位

How can I declare a PtrSafe Sub in VBA? Windows 7, Excel 2016, 64-bit

我正在尝试将我的大数字 VBA 应用程序从 Long 数据类型升级到 LongLong 或 LongPtr 以便能够处理更多数字。 但是我不知道如何调用这个 PtrSafe Sub...一些帮助会很有帮助。

我尝试了一个简单的示例 Sub 来隔离问题。 但是不知道我应该调用哪个 Lib,最重要的是:这个 Sub 应该是 Private 还是 Public?

Public Declare PtrSafe Sub Example Lib "??????" (ByVal x, y, z As LongPtr)

Dim x, y, z As LongPtr

x = 123456789
y = 123456789
MsgBox z = x * y

End Sub

任何人都可以逐步向我解释如何调用 PtrSafe 的 Sub 吗?

PtrSafe

使用 PtrSafe 只是为了在 64 位系统上启用 32 位 API 调用,如下所示:

Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hDC As LongPtr, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long

Public Sub TestScreenResolution()
    Debug.Print ScreenResolution
End Sub
Private Function ScreenResolution() As Double
     Dim hDC As LongPtr
     hDC = GetDC(0)
     ScreenResolution = GetDeviceCaps(hDC, 88)
     ReleaseDC 0, hDC
End Function

条件编译

您可以通过条件编译同时使用两者

#If Win64 Then
    Private Declare PtrSafe Function MakeSureDirectoryPathExists _
        Lib "imagehlp.dll" (ByVal DirPath As String) As Boolean
#Else
    Private Declare Function MakeSureDirectoryPathExists Lib _
        "imagehlp.dll" (ByVal DirPath As String) As Boolean
#End If

你自己的带有 64 位变量的 Sub 或 Function

这些可以这样声明:

Public Sub TestMySub()
    Call MySub(123456789, 123456789)
End Sub

Private Sub MySub(ByVal x As LongLong, ByVal y As LongPtr)
    Dim z As LongLong
    z = x * y
    MsgBox z
End Sub

我希望 Private 尽可能长,并且 Public 仅在需要 "external" 访问权限时。

数据类型 LongLong 与 LongPtr 与 Decimal

在 64 位上 LongLongLongPtr 都是一个 "LongLong Integer" 8 字节:
-9.223.372.036.854.775.808 到 9.223.372.036.854.775.807

但请注意:但是如果您使用 LongLong,它只能在 64 位上工作,其中 32 位上的 LongPtr 将被简单地处理为 4 个字节的 Long,这结果
-2.147.483.648 到 2.147.483.647

因此,如果您确实需要在两个系统上都使用高值并且 Long 还不够,请考虑使用 Double(8 字节,包括舍入效果!)或 Decimal(14 字节,必须首先声明为 Variant):

Private Sub DataTypeDecimal()
    ' Decimal only via declaration as Variant and type cast as Decimal
    Dim d As Variant
    d = CDec("79.228.162.514.264.337.593.543.950.335")
    Debug.Print d
    d = CDec("-79.228.162.514.264.337.593.543.950.335")
    Debug.Print d
End Sub

我给你的例子没问题,谢谢你:-)。

但是现在实际的应用程序说 "type mismatch" 在我尝试用 'True'-布尔值填充 Arr(z)(摘录)(它对 Long 数据类型很好):

Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hDC As LongPtr, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long

Public Sub TestScreenResolution()
    Debug.Print ScreenResolution
End Sub
Private Function ScreenResolution() As Double
     Dim hDC As Long
     hDC = GetDC(0)
     ScreenResolution = GetDeviceCaps(hDC, 88)
     ReleaseDC 0, hDC
End Function

Public Sub TestMySub()
    Call MySub(999999999)
End Sub
Private Sub MySub(ByVal x As LongLong)

Dim z As LongLong
Dim Max, Min As LongLong

Max = x * x
Min = (x - 2) * (x - 2)

Dim Arr() As Boolean 'Default Boolean type is False
ReDim Arr(Min To Max)

For z = Max To Min Step -2
    Arr(z) = True
Next z

End Sub