【问题标题】:How do I display open IE tabs as DWM thumbnails?如何将打开的 IE 选项卡显示为 DWM 缩略图?
【发布时间】:2012-02-10 22:25:45
【问题描述】:

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

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

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

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

【问题讨论】:

标签: c# winapi aero dwm


【解决方案1】:

这段代码枚举了IE缩略图对应的窗口句柄,可以作为DwmRegisterThumbnail functionhwndSource参数使用

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, TabThumbnailWindow 是我在尝试中遗漏的关键部分。
  • 请注意,此类名称未记录在案。无法保证 IE 的未来版本会以相同的方式运行。确保您的客户了解您有意依赖无证行为。
  • @RaymondChen - 有记录的方法吗?不幸的是,如果我理解正确的话,没有 TaskBar 接口能够列出已向 ITaskList3:RegisterTab 注册的内容。
  • 我不知道这方面的文档接口。
  • @RobertS。哦,是的,当然,但是这些 TabThumbnailWindow 窗口存在的事实,或者任何带有适合标题的窗口本身,都没有记录。如果 Raymond Chen 说没有记录在案的方法,那么他是对的 - 关于 Windows,他总是对的 :-)
【解决方案2】:

更新

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

hwndSource

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

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


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

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

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

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

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

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

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

因此,您需要先通过“框架选项卡”类进行迭代,然后通过第二次调用 FindWindowEx() 来检索每个“Internet Explorer_Server”子窗口(尽管您可能想尝试一下,是否通过第三个参数lpszClass 将子级向上传递会产生相同或更好的结果)。

祝你好运!

【讨论】:

  • @Steffen Opel - 虽然这似乎是个好主意,但这不起作用。层次结构在那里,但没有合适的缩略图创建窗口。 IEFrame下的所有窗口在你尝试调用DwmRegisterThumbnail时都会报错。​​
  • @SimonMourier:感谢您对此进行实际测试,我确实只是根据对用例和手头问题的明显草率理解来回答;)因此,我更新了我的答案以解释导致错误并改为推广您的解决方案 (+1)。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 2017-09-13
    • 1970-01-01
    • 2011-06-25
    • 2016-08-03
    • 2021-10-12
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 2011-07-29
    相关资源
    最近更新 更多