如何将打开的IE标签显示为DWM缩略图?

Rob*_* S. 11 c# winapi aero dwm

我在C#中构建一个WPF应用程序,我想在列表框中显示打开的IE选项卡的缩略图.我本质上是在尝试复制Windows 7中的DWM功能.

Windows 7显示打开的IE选项卡

我已经想出如何使用Interop.ShDocVW枚举打开的选项卡列表,但是为了使用DWM API调用,我必须传入一个hwnd,并且选项卡都与Internet Explorer共享相同的句柄.

所以,我一直在搞乱EnumWindowsEnumChildWindows,但我不能得到任何工作.

关于如何最好地接近这个的任何建议?

Sim*_*ier 6

此代码枚举与IE缩略图对应的窗口句柄,可用作DwmRegisterThumbnail函数hwndSource参数

public static IEnumerable<IntPtr> EnumerateIEDwmThumbnails()
{
    List<IntPtr> ptrs = new List<IntPtr>();
    StringBuilder cls = new StringBuilder(100);
    EnumWindows((hwnd, lparam) =>
    {
        GetClassName(hwnd, cls, cls.Capacity);
        if (cls.ToString() == "TabThumbnailWindow")
        {
            ptrs.Add(hwnd);
        }
        return true;
    }, IntPtr.Zero);
    return ptrs;
}

[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsCallback lpEnumFunc, IntPtr lParam);
private delegate bool EnumWindowsCallback(IntPtr hwnd, IntPtr lParam);

[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
Run Code Online (Sandbox Code Playgroud)

  • 请注意,此类名称未记录.无法保证IE的未来版本的行为方式相同.确保您的客户了解您有意依赖未记录的行为. (4认同)
  • @RobertS.哦,是的,当然,但是这些TabThumbnailWindow窗口存在的事实,或任何适合标题的窗口本身都没有记录.如果雷蒙德陈说没有记录的方式,那么他是对的 - 他总是对Windows有用:-) (3认同)

Ste*_*pel 5

更新

虽然确实在问题中指出,但我实际上没有特别关注DWM Thumbnail APIDwmRegisterThumbnail函数的要求:

hwndSource

窗口的句柄用作缩略图源.将源窗口句柄设置为顶级窗口类型以外的任何内容将导致返回值为E_INVALIDARG.[强调我的]

强调的要求使得通过下面概述的FindWindowEx()检索到的子窗口的方法无效,即只能使用FindWindow()来检索顶级窗口的句柄(感谢Simon指出这一点) - Simon的答案提供了基于顶级IE窗口的类名称的适当解决方案,显然是专门为此目的而呈现的.


[...]为了使用DWM API调用,我必须传入一个hwnd,并且所有选项卡都与Internet Explorer共享相同的句柄.

你是如何检查窗口层次结构的?如果我用例如Spy ++检查IE 9窗口,它会公开以下Window类的层次结构(缩写):

  • IEFrame
    • [...]
    • 框架选项卡
      • [...]
    • 框架选项卡
      • [...]
      • TabWindowClass
        • Shell DocObject视图
          • Internet Explorer_Server

子窗口有单独的句柄,所以(从我的头顶)你应该能够通过适当调用FindWindowEx函数来检索所需的句柄,例如:

HWND hwndIeTab = ::FindWindowEx(hwndIeFrame, NULL, "Internet Explorer_Server", NULL);
Run Code Online (Sandbox Code Playgroud)

为了获取所有需要的标签,你需要第二个参数的方法来遍历结果hwndChildAfterFindWindowEx() :

子窗口的句柄.搜索从Z顺序中的下一个子窗口开始.子窗口必须是hwndParent的直接子窗口,而不仅仅是后代窗口.

因此,您需要首先通过类"Frame Tab"进行迭代,然后依次调用FindWindowEx()来检索每个"Internet Explorer_Server"子窗口(尽管您可能需要进行实验,无论是否将孩子传递到第3个参数lpszClass产生相同或更好的结果).

祝好运!


Rob*_* S. 1

我采用的解决方案是使用Win32 API 中的EnumWindowsand 。GetWindowText我使用枚举了 Internet Explorer 窗口,shdocvw.dll并将选项卡的标题传递给解析结果的方法,GetWindowText以查找具有该标题的窗口的 hwnd。

这适用于所有 IE 窗口,而不仅仅是选项卡。