查找已禁用/隐藏[控件]的hWnd

时间:2011-11-10 03:20:46

标签: c# winapi pinvoke

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

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

因此...

是否有任何winapi在找到禁用和隐藏的窗口的同时找到相同级别的WindowFromPoint的窗口/控件?

4 个答案:

答案 0 :(得分:3)

带有CWP_ALL的ChildWindowFromPointEx(如果你想跳过透明窗口则为CWP_SKIPTRANSPARENT,如果你想跳过透明窗口),直到它返回NULL,我想,如果你只是在寻找窗口。

Aussay Marshal指出,控件没有通用定义,Internet Explorer中的控件没有窗口化,与WPF或Java Foundation Classes等其他框架中的控件无关。

如果您正在编写类似Spy ++的内容,请检查Spy++ Internals。如果您需要自动执行其他程序,请选中Windows Automation API

答案 1 :(得分:1)

在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;
}

答案 2 :(得分:0)

如果你真的想要隐藏窗户,你唯一真正的选择是自己走过HWND树;所有...... FromPoint完全跳过这些。 (请注意,隐藏的窗口可能会有一些位置最终阻止您进入它们下面的可见窗口 - 因此您可能想要考虑是否确实想要在所有情况下都隐藏窗口,或者仅作为后备窗口在某一点上没有其他最合适的可见窗口。)

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

要确定HWND的子级,可以使用EnumWindows,也可以使用GetWindow() - 但请注意,如果窗口在枚举时更改zorder,GetWindow可能会给出不一致的结果。

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

检查“点在此HWND中”是比较棘手的:检查窗口中的点是否为第一次测试;但是你可能还必须测试它没有响应HT_TRANSPARENT到WS_EX_TRANSPARENT - 这就是groupbox用来允许点击“遍历”到他们看起来包含的兄弟姐妹的地方。 (你可能还需要考虑形状的窗户 - 那些使用SetWindowRgn给它们一个不规则的形状;现在它们有点罕见,现在将窗口分层到相同的工作。)

-

顺便说一句,如果你不关心隐形窗口,那么考虑使用一个可访问性API:他们已经做了类似的工作。使用AutomationElement.FromPoint,您可以“在那时”获取UI元素。如果你特别关心UI而不是HWND,那就太棒了;它将返回一个表示列表框中项目的对象,而不是整个列表框HWND,以HWND为中心的方法将为您提供 - 但它不会帮助您隐藏窗口。

答案 3 :(得分:-1)

你不能。您无法获得Web浏览器中的Windows类文本框所属的内容。