Как отображать открытые вкладки IE в виде миниатюр DWM?
Я создаю WPF-приложение на С#, и я хочу отображать миниатюры открытых вкладок IE в списке. Я по сути пытаюсь дублировать функции DWM в Windows 7.
![Windows 7 showing open IE tabs]()
Я выяснил, как перечислять список открытых вкладок с помощью Interop.ShDocVW, но для использования вызовов API DWM мне нужно передать hwnd
, а вкладки все имеют один и тот же дескриптор, что и Интернет Проводник.
Итак, я возился с EnumWindows
и EnumChildWindows
, но я не могу заставить что-то работать.
Любые предложения о том, как наилучшим образом подойти к этому?
Ответы
Ответ 1
В решении, с которым я работал, использовались EnumWindows
и GetWindowText
из Win32 API. Я перечисляю через окна Internet Explorer с помощью shdocvw.dll
и передаю заголовок вкладки методу, который анализирует результаты GetWindowText
, чтобы найти hwnd окна с этой надписью.
Это работает для всех окон IE, а не только для вкладок.
Ответ 2
Этот код перечисляет оконные дескрипторы, соответствующие эскизам IE, и может использоваться как параметр hwndSource
функции 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);
Ответ 3
Update
В самом деле, я действительно не рассматривал DWM Thumbnail API и требования функция DwmRegisterThumbnail:
hwndSource
Ручка к окну для использования в качестве источника эскизов. Установка дескриптора окна источника на что-либо, кроме верхнего уровня тип окна приведет к возврату E_INVALIDARG. [акцент мой]
Подчеркнутое требование отображает мой подход с дочерними окнами, полученными с помощью FindWindowEx(), приведенного ниже, недействительным, то есть только FindWindow() может использоваться для извлечения дескриптора в окно верхнего уровня вместо этого (спасибо Саймону за это указание) - Саймон answer предоставляет подходящее решение, основанное на имени класса окна IE верхнего уровня, видимо, созданного специально для этой цели.
[...], чтобы использовать вызовы API DWM, мне нужно передать hwnd, а вкладки все имеют один и тот же дескриптор, что и Internet Explorer.
Как вы проверили иерархию окон? Если я проверю окно IE 9, например. Spy ++, он предоставляет следующую иерархию классы окон (сокращенно):
- IEFrame
- [...]
- Вкладка Frame
- Вкладка Frame
- [...]
- TabWindowClass
- Просмотр оболочки DocObject
У дочерних окон есть отдельные дескрипторы, поэтому (с верхней части головы) вы сможете получить нужные из них с помощью соответствующих вызовов FindWindowEx функции, например:
HWND hwndIeTab = ::FindWindowEx(hwndIeFrame, NULL, "Internet Explorer_Server", NULL);
Чтобы получить все нужные вкладки, вам необходимо выполнить итерацию результатов с помощью второго параметра hwndChildAfter
FindWindowEx():
Дескриптор дочернего окна. Поиск начинается со следующего ребенка окна в порядке Z. Детское окно должно быть прямым дочерним окном hwndParent, а не только окно потомков.
Итак, вам нужно будет сначала выполнить итерацию с помощью класса "Вкладка" Рамка "и получить каждое дочернее окно" Internet Explorer_Server "со вторым вызовом FindWindowEx() (хотя вам может понадобиться поэкспериментировать, прохождение ребенка выше через третий параметр lpszClass
производит одинаковые или лучшие результаты).
Удачи!