在 VBA 中,如果我在 64 位 Office 环境中使用它,我需要
declare
DLL 中具有 ptrSafe
属性的函数。
据我所知,
ptrSafe
在技术上并没有改变任何东西,因此我不确定ptrSafe
属性的实际用途是什么。
PtrSafe
用于告诉 VBA API 声明是安全的: Ptr (pointer)
Safe (safe, safe)
此属性表明我们的目标是 64 位版本。
例如
采用
ShellExecute
API 函数,它可以在不知情的情况下在其默认应用程序中打开任何文件。例如,.xlsx 文档将在 Excel 中打开,.pdf 将在 Acrobat Reader 中打开,除非您安装了其他 PDF 阅读器(例如 Sumatra PDF)。
该函数的API声明已更改为
64-bit
版本。要使 32 and 64-bit
版本共存于同一个数据库中,请编写以下内容:
' --- DECLARATION API WINDOWS
#If VBA7 Then
Private Declare PtrSafe Function ShellExecute _
Lib "shell32.dll" _
Alias "ShellExecuteA" ( _
ByVal hwnd As LongPtr, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) _
As LongPtr
#Else
Private Declare Function ShellExecute _
Lib "shell32.dll" _
Alias "ShellExecuteA" ( _
ByVal hwnd As Long, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) _
As Long
#End If
实际上,就我而言,该关键字除了确保旧代码不会在VBA7中编译之外没有任何作用。这会导致 Microsoft Office 可能向尝试在 VBA7 中运行 32 位代码的用户提供标准错误。否则代码可能会崩溃,在某些情况下可能会发生在 Workbook_Open
或类似的“随机”情况。就我个人而言,我认为关键字的引入是糟糕的设计,并且导致了VBA和VB6之间的分裂。除了用户添加了关键字之外,关键字
PtrSafe
的使用实际上并不能提供任何保证。它不保证他们已检查句柄并将其转换为
LongPtr
。由于这种糟糕的设计,我们现在需要使用复杂的宏来编译 64 位和 32 位 Office 的代码...
#if Win64 then
Private Const NULL_PTR as LongLong = 0^
#else
Private Const NULL_PTR as Long = 0&
#end if
#if VBA7 then
Private Declare PtrSafe Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = NULL_PTR) As Long
'...
#else
Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As Long = NULL_PTR) As Long
'...
#end if
不,相反,微软会更好:
LongPtr
类型。
Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
即使他们没有发布 32 位 VBA/VB6 补丁,我们仍然可以使用宏和枚举:
#If VBA7 = 0 then
Enum LongPtr
[_]
End Enum
#End If
Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
'...
但是可惜,由于引入了此关键字,我们现在必须将所有语句定义两次:
#If VBA7 then
Private Declare PtrSafe Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
'...
#Else
Enum LongPtr
[_]
End Enum
Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
'...
#End If
如果我是 Microsoft,我会将 PtrSafe
关键字设置为可选。这样做将会造福世界。