Excel的Application.Hwnd属性能在64位VBA中使用吗?
Excel的Application.Hwnd属性能在64位VBA中使用吗?
我需要从在电子表格中运行的64位VBA代码中获取Excel 2013 x64窗口句柄。有几种方法可以做到这一点:
- 读取
Application.Hwnd
(MSDN Application.Hwnd 属性 (Excel)) - 调用FindWindow函数,从user32库中导入,例如在这里的被接受的答案中所描述的:VBA 6.0和VBA 7.0之间的区别是什么?:
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As LongPtr
问题是,Application.Hwnd
返回的是一个Long
,即32位(我在64位环境中使用MsgBox TypeName(Application.Hwnd)
进行了验证),而FindWindow
返回的是一个LongPtr
,在Office x64中是64位长。
这是否意味着在64位环境中无法始终相信Application.Hwnd
属性是正确的?
Excel的Application.Hwnd属性在64位VBA中可用吗?
这个问题的出现是因为在64位版本的Office 2010中,LongPtr是一个变量数据类型,它在32位版本上是一个4字节的数据类型,在64位版本上是一个8字节的数据类型。LongPtr的介绍可以在这里阅读。
如果上述链接失效...
LongPtr(32位系统上的Long整数,64位系统上的LongLong整数)变量被存储为有符号32位(4字节)数字,其值范围为-2,147,483,648到2,147,483,647,64位系统上的有符号64位(8字节)数字,其值范围为-9,223,372,036,854,775,808到9,223,372,036,854,775,807。
注意
LongPtr不是一个真正的数据类型,因为它在32位环境中转换为Long,在64位环境中转换为LongLong。使用LongPtr可以编写可在32位和64位环境中运行的可移植代码。对于指针和句柄,请使用LongPtr。
建议进一步阅读:
兼容性:32位和64位Office 2010版本之间的兼容性
从评论中的跟进
然而,我担心由于FindWindow可能返回一个较大的值,窗口句柄可能会超过32位的值。如果是这样,那么Application.Hwnd将无法返回正确的值。或者你是说窗口句柄永远不会超过32位?
以下链接很好地解释了这个问题。
32位和64位应用程序之间的进程间通信
非常感谢您的回答。让我确定一下:FindWindow返回64位,这表明窗口句柄可以超过32位的值。然而,Application.Hwnd只返回32位。所以如果一个窗口句柄的值超过32位的最大值,Application.Hwnd会发生什么?
我不确定是否理解您的意思。如果应用程序hwnd为11872538,则Findwindow将返回相同的值。您还可以使用Spy++来检查。64位的Findwindow使用LongPtr进行兼容性处理,因为某些应用程序可能具有更大的hwnd。
感谢您的回复。我了解如果句柄的值介于-2,147,483,648和2,147,483,647之间,那么两种方式都会返回相同的值。然而,我担心由于FindWindow可以返回一个较大的值,窗口句柄可能会超过32位的值。如果是这样,那么Application.Hwnd将无法返回正确的值。或者你是说窗口句柄永远不会超过32位?
“或者你是说窗口句柄永远不会超过32位?”对于这个我不确定,所以我不会对此发表评论。我可以确定的是,对于同一个窗口,Findwindow和Application.Hwnd不会给出不同的值。这也可以使用Spy++来验证。
刚刚发现这个链接。
-rout - 回答很好,但我不知道Microsoft在编译器中实际上对PtrSafe声明和LongPtr数据类型做了什么,除了在32位和64位互操作性方面进行运行时检查之外:我会猜测LongPtr地址和内存的垃圾回收方式与普通整数不同,因为“安全指针”概念不仅仅是32位兼容性实现。