查找禁用/隐藏[控件]的数量

本文关键字:控件 隐藏 查找 | 更新日期: 2023-09-27 18:14:17

我正在制作一个程序来检测鼠标指向的窗口/控件(非常类似于spy++),但是我遇到了一个问题:

原来我一直在使用WindowFromPoint来查找控件的hWnd,但发现禁用/隐藏的窗口不显示。每个网站都说使用ChildWindowFromPoint(或类似的winapi),但是这些都没有在窗口内找到控件。

所以…

是否有任何winapi可以找到与WindowFromPoint相同级别的窗口/控件,同时仍然可以找到禁用和隐藏的窗口?

查找禁用/隐藏[控件]的数量

ChildWindowFromPointEx与CWP_ALL(或CWP_SKIPTRANSPARENT,如果你想跳过透明窗口)在一个循环,直到它返回NULL,我猜,如果你只是在寻找窗口。

控件没有统一的定义,正如Aussay Marshal指出的,ie中的控件不是窗口的,与WPF或Java Foundation Classes等其他框架中的控件没有任何关系。

如果你正在写类似spy++的东西,检查spy++的内部。如果您需要自动化其他程序,请检查Windows自动化API。

这在c++中适用:

HWND ChildFromPoint_recurse(HWND inHWND, POINT inPOINT)
{
    HWND lHWND = ChildWindowFromPointEx(inHWND,inPOINT,CWP_ALL);
    if (lHWND == 0) return inHWND;
    if (lHWND != inHWND)
    {
        POINT lPOINT = inPOINT;
        if (!ClientToScreen(inHWND,&lPOINT)) return lHWND;
        if (!ScreenToClient(lHWND,&lPOINT)) return lHWND;
        HWND lHWNDrecurse = ChildFromPoint_recurse(lHWND,lPOINT);
        if (lHWNDrecurse) lHWND = lHWNDrecurse;
    }
    return lHWND;
}

如果你真的想要隐藏窗口,你唯一的选择就是自己遍历HWND树;所有的…FromPoint直接跳过这些。(请注意,隐藏窗口的位置可能会阻止你看到"下面"的可见窗口——所以你可能要考虑是否真的想在所有情况下都看到隐藏窗口,或者只是在没有其他最合适的可见窗口的情况下作为备用。)

使用GetDesktopWindow()从根开始,然后适当地下降;遍历每一个子节点,看看该点是否在其中,如果是,遍历该分支并忽略其他兄弟节点。

要确定HWND的子节点,您可以使用EnumWindows或使用getwwindow() -但请注意,如果在枚举它们时窗口更改了zorder, getwwindow可能会给您不一致的结果。

然后由你来决定如何过滤掉hwnd;如果您只想要可见窗口,那么跳过那些没有设置WS_VISIBLE位的窗口。

检查"point is in this HWND"更棘手:检查point in window rect是第一个测试;但您可能还必须测试它是否对WS_EX_TRANSPARENT不响应HT_TRANSPARENT——这是组框用来允许点击"通过"到它们似乎包含的兄弟节点的方法。(你可能还需要考虑形状的窗口-那些使用setwindowgn给他们一个不规则的形状;现在把Windows分层到相同的工作上已经很少见了。

,

作为题外话,如果你不关心不可见窗口,那么考虑使用一个可访问性api:它们已经做了类似的工作。使用AutomationElement。FromPoint,你可以得到UI元素"在那个点"。如果你真的关心UI而不是hwnd,这是很好的;它将返回一个对象,表示列表框中的一个项目,而不是整个列表框HWND,以HWND为中心的方法将得到你-但它不会帮助你隐藏窗口

你不能。