如何将打开的 IE 选项卡显示为 DWM 缩略图?

发布于 2025-01-04 11:47:59 字数 391 浏览 3 评论 0原文

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

Windows 7 显示打开的 IE 选项卡

我已经弄清楚如何使用 Interop.ShDocVW 枚举打开的选项卡列表,但为了使用 DWM API 调用,我必须传入 hwnd,并且所有选项卡共享相同的句柄互联网浏览器。

所以我一直在搞乱 EnumWindowsEnumChildWindows 但我无法让任何东西工作。

关于如何最好地解决这个问题有什么建议吗?

I am building a WPF application in C# and I want to display thumbnails of open IE tabs in a listbox. I'm essentially trying to duplicate the DWM functionality in Windows 7.

Windows 7 showing open IE tabs

I have figured out how to enumerate a list of open tabs using Interop.ShDocVW, but in order to use the DWM API calls, I have to pass in an hwnd, and the tabs all share the same handle as Internet Explorer.

So I've been messing with EnumWindows and EnumChildWindows but I can't get anything to work.

Any suggestions on how to best approach this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

_畞蕅 2025-01-11 11:47:59

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

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

This code enumerates window handles that correspond to IE thumbnails and can be used as the hwndSource parameter of the DwmRegisterThumbnail function

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);
听你说爱我 2025-01-11 11:47:59

更新

虽然确实在问题中指定,但我实际上并没有研究 DWM 缩略图 APIDwmRegisterThumbnail 函数 具体为:

hwndSource

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

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


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

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

  • IE框架
    • [...]
    • 框架选项卡
      • [...]
    • 框架选项卡
      • [...]
      • TabWindow类
        • 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 更高的子级会产生相同或更好的结果)。

祝你好运!

Update

While specified in the question indeed, I hadn't actually looked into the DWM Thumbnail API and the requirements of the DwmRegisterThumbnail function specifically:

hwndSource

The handle to the window to use as the thumbnail source.
Setting the source window handle to anything other than a top-level
window type
will result in a return value of E_INVALIDARG. [emphasis mine]

The emphasized requirement renders my approach with child windows retrieved via FindWindowEx() outlined below invalid, i.e. only FindWindow() might be used to retrieve a handle to a top-level window instead (thanks Simon for pointing this out) - Simon's answer provides an appropriate solution based on the class name of the top-level IE window apparently rendered specifically for this purpose.


[...] in order to use the DWM API calls, I have to pass in an hwnd, and the
tabs all share the same handle as Internet Explorer.

How have you inspected the window hierarchy? If I inspect an IE 9 window with e.g. Spy++, it exposes the following hierarchy of Window Classes (abbreviated):

  • IEFrame
    • [...]
    • Frame Tab
      • [...]
    • Frame Tab
      • [...]
      • TabWindowClass
        • Shell DocObject View
          • Internet Explorer_Server

The child windows have separate handles, so (from the top of my head) you should be able to retrieve the desired ones via appropriate calls to the FindWindowEx function, e.g.:

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

In order to retrieve all desired tabs, you need to iterate over the results by means of the 2nd parameter hwndChildAfter of FindWindowEx():

A handle to a child window. The search begins with the next child
window in the Z order. The child window must be a direct child window
of hwndParent, not just a descendant window.

So you'd need to iterate via class "Frame Tab" first and retrieve each "Internet Explorer_Server" child window with a second call to FindWindowEx() in turn (though you might want to experiment, whether passing a child higher up via the 3rd parameter lpszClass produces identical or better results).

Good luck!

隐诗 2025-01-11 11:47:59

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

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

The solution I went with was using EnumWindows and GetWindowText from the Win32 API. I enumerate through Internet Explorer windows using shdocvw.dll and pass the tab's caption to a method that parses the results of GetWindowText to find the hwnd of the window with that caption.

This works for all IE windows, not just tabs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文