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

C# 查找禁用/隐藏[控件]的hWnd,c#,winapi,pinvoke,C#,Winapi,Pinvoke,我正在制作一个程序来检测鼠标指向的窗口/控件(非常类似于spy++),但是我遇到了一个问题: 最初我一直在使用WindowFromPoint查找控件的hWnd,但发现禁用/隐藏的窗口不显示。每个站点都说要使用ChildWindowFromPoint(或类似的winapi),但这些站点在windows中找不到控件 所以 是否有winapi在仍然查找禁用和隐藏窗口的情况下查找与WindowFromPoint相同级别的窗口/控件?您不能。您无法获取web浏览器中的windows类tje文本框所属的内容

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

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

所以


是否有winapi在仍然查找禁用和隐藏窗口的情况下查找与WindowFromPoint相同级别的窗口/控件?

您不能。您无法获取web浏览器中的windows类tje文本框所属的内容。

您不能。您无法在web浏览器中获取windows类tje textbox所属的内容。

ChildWindowFromPointEx与CWP_ALL(或CWP_SkiptTransparent,如果您想跳过透明窗口)一起循环,直到它返回NULL,我猜,如果您只在查找windows

Aussay Marshal没有指出控件的通用定义,Internet Explorer中的控件没有加窗,与WPF或java基础类等框架中的控件无关。p>


如果您正在编写类似Spy++的内容,请选中。如果您需要自动执行其他程序,请在循环中使用CWP_ALL(或CWP_SKIPTRANSPARENT,如果您想跳过透明窗口)检查。

ChildWindowFromPointEx,直到它返回NULL为止,我想,如果您只查找窗口的话

Aussay Marshal没有指出控件的通用定义,Internet Explorer中的控件没有加窗,与WPF或java基础类等框架中的控件无关。p>


如果您正在编写类似Spy++的内容,请选中。如果您需要自动化其他程序,请选中。

如果您真的想要隐藏窗口,您唯一的实际选择是自己走HWND树;所有的…从点直接跳过这些。(请注意,隐藏窗口的位置可能最终会阻止您进入“下方”的可见窗口-因此,您可能需要考虑在所有情况下是否真的要进入隐藏窗口,或者只有在某一点上没有其他最合适的可见窗口时才作为备用。)

使用GetDesktopWindow()从根开始,并适当下降;遍历每个子节点,查看该点是否在其中,如果在其中,则向下遍历该分支并忽略其他同级

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

然后由您决定如何过滤HWND;如果您只想要可见的窗口,则跳过未设置WS_visible位的窗口

检查“point is in this HWND”更为棘手:检查window rect中的point是第一个测试;但您可能还需要测试它是否对WS_EX_TRANSPARENT不响应HT_TRANSPARENT-这是GroupBox用来允许单击“通过”到它们似乎包含的兄弟节点。(您可能还需要考虑成型窗口——这些窗口使用SetWindowRgn使其具有不规则的形状;由于分层窗口可以用于相同的工作,因此这些窗口现在有点少见。)

--


顺便说一下,如果你不关心隐形窗口,那么考虑使用一个可访问API:它们已经做了类似的工作。使用AutomationElement.FromPoint,您可以“在该点”获得UI元素。如果你真的关心UI而不是HWND,这是非常好的;它将返回一个对象,该对象表示列表框中的一个项目,而不是整个列表框HWND,以HWND为中心的方法将使您得到它-但它不会帮助您隐藏窗口。

如果您确实想要隐藏窗口,您唯一真正的选择是自己走HWND树;所有的…从点直接跳过这些。(请注意,隐藏窗口的位置可能最终会阻止您进入“下方”的可见窗口-因此,您可能需要考虑在所有情况下是否真的要进入隐藏窗口,或者只有在某一点上没有其他最合适的可见窗口时才作为备用。)

使用GetDesktopWindow()从根开始,并适当下降;遍历每个子节点,查看该点是否在其中,如果在其中,则向下遍历该分支并忽略其他同级

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

然后由您决定如何过滤HWND;如果您只想要可见的窗口,则跳过未设置WS_visible位的窗口

检查“point is in this HWND”更为棘手:检查window rect中的point是第一个测试;但您可能还需要测试它是否对WS_EX_TRANSPARENT不响应HT_TRANSPARENT-这是GroupBox用来允许单击“通过”到它们似乎包含的兄弟节点。(您可能还需要考虑成型窗口——这些窗口使用SetWindowRgn使其具有不规则的形状;由于分层窗口可以用于相同的工作,因此这些窗口现在有点少见。)

--


顺便说一下,如果你不关心隐形窗口,那么考虑使用一个可访问API:它们已经做了类似的工作。使用AutomationElement.FromPoint,您可以“在该点”获得UI元素。如果你真的关心UI而不是HWND,这是非常好的;它将返回一个表示列表框内的项的对象,而不是整个HistNox HWND,它以HWND为中心的方法将获得您——但它将不会帮助您隐藏窗口。

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

这对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;
}

这和我问的问题无关?我不是想得到wi