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

时间:2012-02-10 22:25:46

标签: c# winapi aero dwm

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

Windows 7 showing open IE tabs

我已经弄清楚如何使用Interop.ShDocVW枚举打开的标签列表,但是为了使用DWM API调用,我必须传入hwnd,并且所有标签都共享相同的句柄作为Internet Explorer。

所以我一直在捣乱EnumWindowsEnumChildWindows,但我无法解决任何问题。

有关如何最好地解决这个问题的任何建议吗?

3 个答案:

答案 0 :(得分:6)

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

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);

答案 1 :(得分:5)

更新

虽然确实在问题中有详细说明,但我并没有真正专门研究DWM Thumbnail APIDwmRegisterThumbnail function的要求:

  

hwndSource

     

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

强调的要求使我通过下面列出的FindWindowEx()检索到的子窗口的方法无效,即只有FindWindow()可能用于检索顶级窗口的句柄(感谢Simon指出这一点) out) - Simon's answer提供了一个适当的解决方案,该解决方案基于显然专门为此目的而呈现的顶级IE窗口的类名。


  

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

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

  • IEFrame
    • [...]
    • 框架标签
      • [...]
    • 框架标签
      • [...]
      • TabWindowClass
        • Shell DocObject视图
          • Internet Explorer_Server

子窗口有单独的手柄,因此(从头顶开始)您应该能够通过适当调用FindWindowEx function来检索所需的手柄,例如:

HWND hwndIeTab = ::FindWindowEx(hwndIeFrame, NULL, "Internet Explorer_Server", NULL);

为了检索所有需要的标签,您需要通过 FindWindowEx()的第二个参数hwndChildAfter迭代结果:

  

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

因此,您需要通过课程&#34;框架标签&#34;进行迭代。首先检索每个&#34; Internet Explorer_Server&#34;子窗口依次调用 FindWindowEx()(尽管您可能想要进行实验,是否通过第3个参数lpszClass将孩子传递到更高的位置会产生相同或更好的结果)。< / p> 祝你好运!

答案 2 :(得分:1)

我使用的解决方案是使用Win32 API中的EnumWindowsGetWindowText。我使用shdocvw.dll通过Internet Explorer窗口进行枚举,并将标签的标题传递给解析GetWindowText结果的方法,以查找带有该标题的窗口的hwnd。

这适用于所有IE窗口,而不仅仅是标签。