Как я могу объявить сабвуфер PtrSafe в VBA?Windows 7, Excel 2016, 64-разрядная версия - PullRequest
0 голосов
/ 02 февраля 2019

Я пытаюсь обновить мое большое количество приложений VBA с типа данных Long до LongLong или LongPtr, чтобы иметь возможность обрабатывать больше цифр.Но я не могу понять, как вызвать этот Sub PtrSafe ... Некоторая помощь будет очень полезна.

Я попробовал простой пример 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

Может ли кто-нибудь объяснить мне, как шаг за шагом вызвать Sub,PtrSafe

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

Пример, который я привел вам, работает нормально, спасибо вам за это: -).

Реальное приложение, однако, теперь говорит «несоответствие типов» в тот момент, когда я пытаюсь заполнить Arr (z) 'True'-Booleans (отрывок) (он отлично работал с типом данных 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
0 голосов
/ 02 февраля 2019

PtrSafe

Используйте PtrSafe только для включения 32-битных вызовов API на 64-битных системах, например:

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

Ваш собственный Sub или Function с 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 оба представляют собой "LongLong Integer" с 8 байтами:
-9.223.372.036.854.775.808 до 9.223.372.036.854.775.807

Но имейте в виду: но если вы используете LongLong, он будет работать ТОЛЬКО на 64-битной системе, где LongPtr на32-битный будет обрабатываться просто как Long в 4 байта, что приводит от
-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
...