Vba 如何获取子窗口的hWnd并使用FindWindowEx API激活它

Vba 如何获取子窗口的hWnd并使用FindWindowEx API激活它,vba,ms-access,winapi,Vba,Ms Access,Winapi,我正在使用MS Access 2016 VBA自动访问外部应用程序。外部应用程序窗口有一个显示在子窗口中的视频 如果我使用spyxx.exe,我可以使用Finder工具获得视频控件的句柄,当然,它会更改标题面板、类wxWindowNR和样式52000000。当我使用spyxx.exe返回的句柄时,我可以成功地使用该句柄将正确的应用程序带到顶部并激活它。但由于它可以处理更改,所以我需要使用MS Access VBA动态获取它 我遇到的问题是,当我使用FindWindowEx API尝试获取子视频窗

我正在使用MS Access 2016 VBA自动访问外部应用程序。外部应用程序窗口有一个显示在子窗口中的视频

如果我使用spyxx.exe,我可以使用Finder工具获得视频控件的句柄,当然,它会更改标题面板、类wxWindowNR和样式52000000。当我使用spyxx.exe返回的句柄时,我可以成功地使用该句柄将正确的应用程序带到顶部并激活它。但由于它可以处理更改,所以我需要使用MS Access VBA动态获取它

我遇到的问题是,当我使用FindWindowEx API尝试获取子视频窗口的句柄时,我无法找到如何获取spyxx.exe所产生的相同句柄。以下是我正在尝试的内容和主题的一些变化: 公告如下:

公共声明函数FindWindowEx Lib user32.dll别名FindWindowExA ByVal hwndParent为Long,ByVal hwndChildAfter为Long,ByVal lpszClass为String,ByVal lpszWindow为String为Long

尝试获取子视频窗口句柄的代码是WinHand,其中WinHand是父窗口的句柄:

FindWindowEx(WinHand, 0, "wxWindowNR", "panel")
我知道WinHand对于父窗口是正确的,因为使用WinHand我可以使应用程序成为最活跃的窗口。但是,我无法让FindWindowEx返回spyxx.exe显示的句柄是子面板窗口的句柄

当我将子窗口的名称留空时,它会返回句柄,如下所示:

FindWindowEx(WinHand, 0, "wxWindowNR", "")
但决不能使用spyxx.exe显示的正确句柄


从每天大部分时间的网络搜索来看,我似乎需要对EnumChildWindows API做些什么,但我不知道如何在MS Access VBA中引用它,也不知道如何循环返回的窗口以找到面板窗口句柄。

为了方便将来可能遇到类似问题的人,我正在发布我使用的解决方案,虽然我希望看到使用EnumChildWindows提供的解决方案,因为这似乎是更优雅的方法,但我对API不够了解,不知道如何设置它

FindWindowEx找不到我正在查找的儿童视频控件窗口,因为该控件是作为父母的子女的子女的子女而埋下的。FindWindowEx将只搜索前一个父项的子项。因此,必须嵌套对隐藏的子控件的搜索

我采取了以下步骤:

打开需要从VBA访问其窗口和子窗口的目标应用程序。 运行Spyxx.exe aka Spy++ 使用“查找窗口”工具,获取所需句柄的子窗口控件的句柄、标题和类 记下这些项目,然后关闭“查找窗口”工具 仍在使用Spyxx.exe,请使用菜单项Tree/Save Tree to File。。。或者按CTRL+S将窗口树保存到文本文件中请注意,保存默认为将其保存为.sxt Spy++对象,此处不需要该对象 打开保存在您最喜爱的文本编辑器中的windows文本文件的树列表,我使用Notepad++对其进行了良好的格式化,然后搜索您在上面步骤3和4中提到的窗口句柄 这将在树中找到所需的子窗口 现在,按照以下步骤在树上向后操作,直到到达父窗口句柄 记下下下一级窗口的窗口标题。标题用双引号括起来;稍后编写VBA代码时,您将需要该标题 现在向上移动到下一个窗口级别,并向下写入该窗口的标题 继续向上移动窗口级别,直到到达应用程序本身的父窗口 最后一步:现在在VBA代码中,要找到目标子窗口控件的窗口句柄,您必须嵌套FindWindowEx命令,从父窗口开始,按如下方式向下,将wxWindowNR替换为与您试图找到的子控件相关的任何窗口类:

FindWindowEx (ParentWindowHandle, 0, "wxWindowNR", "[caption from steps 9 to 11]")
例如,这里是我必须使用的代码,其中ChildWindow5是我正在寻找的视频控制窗口的句柄;需要While…Wend命令,因为在我所针对的应用程序中,应用程序运行时并非所有子窗口都立即存在:

ParentWindow = 0
While ParentWindow = 0
    ParentWindow = FindWindow("Target Window Caption")
Wend

ChildWindow1 = 0
While ChildWindow1 = 0
    ChildWindow1 = FindWindowEx(CLng(ParentWindow), 0, "wxWindowNR", "ID_BOOKMARK_SPLITTERWINDOW")
Wend

ChildWindow2 = 0
While ChildWindow2 = 0
    ChildWindow2 = FindWindowEx(CLng(ChildWindow1), 0, "wxWindowNR", "ID_TOPPANEL_SPLITTERWINDOW")
Wend

ChildWindow3 = 0
While ChildWindow3 = 0
    ChildWindow3 = FindWindowEx(CLng(ChildWindow2), 0, "wxWindowNR", "ID_MAINDISPLAY_PANEL")
Wend

ChildWindow4 = 0
While ChildWindow4 = 0
    ChildWindow4 = FindWindowEx(CLng(ChildWindow3), 0, "wxWindowNR", "ID_VIDEODISPLAY_PANEL")
Wend

ChildWindow5 = 0
While ChildWindow5 = 0
    ChildWindow5 = FindWindowEx(CLng(ChildWindow4), 0, "wxWindowNR", "panel")
Wend
请注意,对子窗口句柄的每个后续搜索都引用先前的父窗口


这对我很管用。我仍然认为,如果有人能指出如何使用EnumChildWindows来实现这一点,那么解决方案可能会更加优雅。

你的手柄搞错了吗?你有什么把柄?可能存在另一个具有类名的窗口。你应该在Spy++中找到错误的句柄,谢谢@xMRi。Spy++没有找到错误的句柄。我知道Spy++返回的句柄是正确的,因为当我在VBA代码中使用Spy++句柄时,代码可以操作目标子窗口。我
need是一种获得Spy++通过使用VBA FindWindowEx或EnumChildWindows找到的相同句柄的方法。显然,FindWindowEx现在返回的句柄是不正确的,但是我无法确定如何更正它以找到Spy++找到的句柄。这就是问题所在:如何让VBA找到Spy++找到的相同正确句柄?您得到了什么句柄?当目标窗口关闭并重新打开时,该句柄的数目当然会改变。但是Spy++每次都能找到正确的句柄,但是VBA从来没有使用FindWindowEx找到正确的句柄。我知道这一点,因为如果我使用Spy++返回的句柄,我可以在VBA中操纵目标窗口,但是,如果我使用VBA返回的句柄,我无法操纵目标窗口。因此,VBA必须返回错误的句柄,而Spy++必须返回正确的句柄。问题是:如何让VBA返回与Spy++相同的正确句柄?为什么要投反对票?如果有人认为这是一个糟糕的问题,请张贴为什么这是一个糟糕的问题,或者,请张贴明显的答案。可能否决票是因为你没有给我们写足够的信息。你有什么把柄?FindWindow永远不会返回不存在的东西。。。因此,如果您得到一个结果,该窗口将与条件匹配。由于你不能给我们展示一个可复制的代码,否决票可能是一个结果。您是否使用GetWindowAPI函数自己遍历窗口树?