declare 语句的 ptrSafe 属性的用途是什么

问题描述 投票:0回答:2

在 VBA 中,如果我在 64 位 Office 环境中使用它,我需要

declare
DLL 中具有
ptrSafe
属性的函数。

据我所知,

ptrSafe
在技术上并没有改变任何东西,因此我不确定
ptrSafe
属性的实际用途是什么。

vba 32bit-64bit
2个回答
1
投票

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

原创内容可以在那里找到


0
投票

实际上,就我而言,该关键字除了确保旧代码不会在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
不,相反,微软会更好:

    发布了 32 位 VBA 和 VB6 的补丁,添加了
  1. LongPtr
     类型。
  2. 保持旧的声明语法不变
如果这样做了,以下内容就足以满足 32 位和 64 位系统的需要:

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

 关键字设置为可选。这样做将会造福世界。

© www.soinside.com 2019 - 2024. All rights reserved.