2

我正在尝试将我的大量 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?

4

2 回答 2

4

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 位变量的子或函数

这些可以这样声明:

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只有在需要“外部”访问的情况下。

数据类型 LongLong 与 LongPtr 与 Decimal

在 64 位上LongLong并且LongPtr都是 8 字节的“LongLong 整数”:
-9.223.372.036.854.775.808 到 9.223.372.036.854.775.807

但请注意:但如果您使用LongLong,它只能在 64 位上工作,LongPtr在 32 位上将被简单地处理为Long4 个字节,这导致
-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
于 2019-02-02T18:59:46.907 回答
-1

我给你的例子很好用,谢谢你:-)。

然而,当我尝试用'True'-Booleans(摘录)填充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
于 2019-02-03T07:31:49.670 回答