使用Word VBA获取其他已打开应用窗口Window ID的问题
64位VBA窗口句柄获取代码报错解决
编辑说明
发布问题后我意识到,代码实际上并未切换到其他窗口,但可以获取Window ID编号。因此我修改了问题以反映代码的实际功能。我已让代码在64位环境下运行,处理完Eugene Astafiev的回答建议后会发布答案。
问题描述
我在多个线程中找到一段32位的代码,尝试将其转换为64位版本,当前代码如下:
API声明部分
Option Explicit Private Declare PtrSafe Function FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As LongPtr, ByVal lpString As String, ByVal cch As LongPtr) As Long Private Declare PtrSafe Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hWnd As LongPtr) As Long Private Declare PtrSafe Function GetWindow Lib "user32" (ByVal hWnd As LongPtr, ByVal wCmd As Long) As LongPtr Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hWnd As LongPtr) As Boolean Private Const GW_HWNDNEXT = 2
Test过程
Private Sub Test() Dim lhWndP As Long If GetHandleFromPartialCaption(lhWndP, "Excel") = True Then If IsWindowVisible(lhWndP) = True Then MsgBox "Found VISIBLE Window Handle: " & lhWndP, vbOKOnly + vbInformation Else MsgBox "Found INVISIBLE Window Handle: " & lhWndP, vbOKOnly + vbInformation End If Else MsgBox "Window 'Excel' not found!", vbOKOnly + vbExclamation End If End Sub
获取句柄函数
Private Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal sCaption As String) As Boolean Dim lhWndP As Long Dim sStr As String GetHandleFromPartialCaption = False lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW Do While lhWndP <> 0 sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0)) GetWindowText lhWndP, sStr, Len(sStr) sStr = Left$(sStr, Len(sStr) - 1) If InStr(1, sStr, sCaption) > 0 Then GetHandleFromPartialCaption = True lWnd = lhWndP Exit Do End If lhWndP = GetWindow(lhWndP, GW_HWNDNEXT) Loop End Function
运行Test过程时,执行到函数最后一行出现错误(错误截图:
)。我花了很多时间查找64位的API声明调整方式,是否有遗漏的地方?
更新
发布问题后我发现未将FindWindow函数声明为LongPtr。修正后,现在又在代码开头出现Type mismatch(类型不匹配)错误(错误截图:
)。
解决方法
报错核心是变量类型与64位句柄不兼容:64位系统中窗口句柄是8字节的LongPtr类型,但代码里多处用4字节的Long存储句柄,导致类型冲突。
修正后的完整代码
Option Explicit Private Declare PtrSafe Function FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As LongPtr, ByVal lpString As String, ByVal cch As LongPtr) As Long Private Declare PtrSafe Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hWnd As LongPtr) As Long Private Declare PtrSafe Function GetWindow Lib "user32" (ByVal hWnd As LongPtr, ByVal wCmd As Long) As LongPtr Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hWnd As LongPtr) As Boolean Private Const GW_HWNDNEXT = 2 Private Sub Test() Dim lhWndP As LongPtr ' 改为LongPtr If GetHandleFromPartialCaption(lhWndP, "Excel") = True Then If IsWindowVisible(lhWndP) = True Then MsgBox "找到可见窗口句柄: " & lhWndP, vbOKOnly + vbInformation Else MsgBox "找到不可见窗口句柄: " & lhWndP, vbOKOnly + vbInformation End If Else MsgBox "未找到包含'Excel'的窗口!", vbOKOnly + vbExclamation End If End Sub Private Function GetHandleFromPartialCaption(ByRef lWnd As LongPtr, ByVal sCaption As String) As Boolean ' 参数改为LongPtr Dim lhWndP As LongPtr ' 改为LongPtr Dim sStr As String GetHandleFromPartialCaption = False lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW Do While lhWndP <> 0 sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0)) GetWindowText lhWndP, sStr, Len(sStr) sStr = Left$(sStr, Len(sStr) - 1) If InStr(1, sStr, sCaption) > 0 Then GetHandleFromPartialCaption = True lWnd = lhWndP Exit Do End If lhWndP = GetWindow(lhWndP, GW_HWNDNEXT) Loop End Function
关键修正点
- 将所有存储窗口句柄的变量(
Test中的lhWndP、GetHandleFromPartialCaption的参数lWnd和内部变量lhWndP)从Long改为LongPtr,确保64位环境下能正确存储8字节句柄。 - API声明部分已正确使用
PtrSafe并返回LongPtr,无需修改。
内容的提问来源于stack exchange,提问作者DryBSMT
相关产品推荐
相关产品推荐

