C++ EnumChildWindows从不调用其回调

C++ EnumChildWindows从不调用其回调,c++,winapi,C++,Winapi,我试图操纵一个特定的InternetExplorer11窗口。使用WinSpy++我发现 顶层窗口的类是一个IEFrame,文档标题为文本(由GetWindowText返回) 实际的web视图类称为“Internet Explorer_Server”,是前者的子类 我编写了一个简单的测试用例,用三种不同的方式查找在“”上打开的IE11的web视图: HWND FindIE_A() { // Use FindWindow, works! HWND hWndTop = ::FindW

我试图操纵一个特定的InternetExplorer11窗口。使用WinSpy++我发现

  • 顶层窗口的类是一个IEFrame,文档标题为文本(由GetWindowText返回)
  • 实际的web视图类称为“Internet Explorer_Server”,是前者的子类
  • 我编写了一个简单的测试用例,用三种不同的方式查找在“”上打开的IE11的web视图:

    HWND FindIE_A()
    {
        // Use FindWindow, works!
        HWND hWndTop = ::FindWindowA( NULL, "Google - Internet Explorer" );
        // Find the web view window, the callback (FindIEServer) is NEVER called!
        HWND hWnd = NULL;
        ::EnumChildWindows( hWndTop, &FindIEServer, (LPARAM)&hWnd );
        return hWnd;
    }
    HWND FindIE_B()
    {
        // Use EnumChildWindows with NULL as parent, works!
        HWND hWndTop = NULL;
        ::EnumChildWindows( NULL, &FindIEMain, (LPARAM)&hWndTop );
        // Find the web view window, the callback (FindIEServer) is NEVER called!
        HWND hWnd = NULL;
        ::EnumChildWindows( hWndTop, &FindIEServer, (LPARAM)&hWnd );
        return hWnd;
    }
    HWND FindIE_C()
    {
        // Simple EnumWindows, works!
        HWND hWndTop = NULL;
        ::EnumWindows( &FindIEMain, (LPARAM)&hWndTop );
        // Find the web view window, the callback (FindIEServer) is NEVER called!
        HWND hWnd = NULL;
        ::EnumChildWindows( hWndTop, &FindIEServer, (LPARAM)&hWnd );
        return hWnd;
    }
    
    回调非常简单;从窗口获取属性并与硬编码值进行比较:

    BOOL CALLBACK FindIEServer( HWND hWnd, LPARAM lParam )
    {
        char className[64];
        ::GetClassNameA( hWnd, className, sizeof(className) );
        if ( !strcmp( className, "Internet Explorer_Server" ) )
        {
            *(HWND*)lParam = hWnd;
            return FALSE;
        }
        return TRUE;
    }
    BOOL CALLBACK FindIEMain( HWND hWnd, LPARAM lParam )
    {
        char text[128];
        ::GetWindowTextA( hWnd, text, sizeof(text) );
        if ( !strcmp( text, "Google - Internet Explorer" ) )
        {
            *(HWND*)lParam = hWnd;
            return FALSE;
        }
        return TRUE;
    }
    

    每次提供父窗口时,EnumChildWindows都失败(根本不调用回调!)。为什么?

    问题是,当我查找窗口标题时,我假设只有一个窗口具有该标题。然而,Internet Explorer做了一些恶作剧,创建了多个具有相同标题的窗口,但其中只有一个具有类IEFrame

    碰巧找到的第一个窗口是错误的,它没有任何子窗口(因此EnumChildWindows没有任何可迭代的对象)。只是增加了一个额外的检查标题+类作品


    然而,正如@wakjah所建议的,最好将IE(或任何其他浏览器)直接集成到您的代码中。通过谷歌,我找到了很多关于如何使用IE和Chrome实现这一点的文档。

    我不知道你的最终目标是什么,但你最好通过COM使用IE自动化。请看一个例子,也许Internet Explorer不希望您欺骗它的孩子。您是否试图在网页中获取控件,例如web表单中的控件?如果是这样,你应该知道。@wakjah我正试图在directx9游戏中嵌入浏览器。我能够捕捉窗口像素并将其流到纹理中并绘制它。我现在希望能够在游戏中控制它。谢谢你的链接,看起来很有趣,我会看看的!
    internetexplorer\u服务器
    窗口不是
    IEFrame
    的直接子窗口,它嵌套了好几层。即使您让
    EnumChildWindows()
    工作,它也不会找到
    internetexplorer\u服务器
    ,除非您多次调用它。在这种情况下,应该使用
    FindWindowEx()
    而不是
    EnumChildWindows()