11

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

Windows 7 显示打开的 IE 选项卡

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

所以我一直在搞砸,EnumWindowsEnumChildWindows我什么都做不了。

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

4

3 回答 3

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);
于 2012-02-13T21:19:52.957 回答
5

更新

虽然确实在问题中指定了,但我实际上并没有具体研究DWM Thumbnail APIDwmRegisterThumbnail 函数的要求:

hwndSource

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

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


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

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

  • 框架
    • [...]
    • 框架选项卡
      • [...]
    • 框架选项卡
      • [...]
      • 选项卡窗口类
        • Shell DocObject 视图
          • Internet Explorer_Server

子窗口有单独的句柄,因此(从我的脑海中)您应该能够通过适当调用FindWindowEx 函数来检索所需的句柄,例如:

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

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

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

因此,您需要先通过“Frame Tab”类进行迭代,然后依次通过第二次调用FindWindowEx()来检索每个“Internet Explorer_Server”子窗口(尽管您可能想试验一下,是否通过第三个更高的子窗口参数lpszClass产生相同或更好的结果)。

祝你好运!

于 2012-02-13T11:03:18.083 回答
1

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

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

于 2012-02-18T00:36:34.200 回答