11

C#でWPFアプリケーションを構築していて、開いているIEタブのサムネイルをリストボックスに表示したいと思います。私は基本的にWindows7でDWM機能を複製しようとしています。

開いているIEタブを表示しているWindows7

Interop.ShDocVWを使用して開いているタブのリストを列挙する方法を理解しましたが、DWM API呼び出しを使用するには、を渡す必要がhwndあり、タブはすべてInternetExplorerと同じハンドルを共有します。

だから私はいじっていEnumWindowsますEnumChildWindowsが、何も動作させることができません。

これに最善のアプローチをする方法について何か提案はありますか?

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 関数の要件を具体的に調べていませんでした。

hwndソース

サムネイル ソースとして使用するウィンドウのハンドル。ソース ウィンドウ ハンドルをトップレベル ウィンドウ タイプ以外に設定すると、戻り値 E_INVALIDARG が返されます。[鉱山を強調]

強調された要件により、以下に概説するFindWindowEx()を介して取得された子ウィンドウを使用した私のアプローチは無効になります。つまり、代わりにFindWindow()のみを使用してトップレベル ウィンドウへのハンドルを取得することができます (これを指摘してくれた Simon に感謝します) - Simon の答えは、明らかにこの目的のために特別にレンダリングされたトップレベルの IE ウィンドウのクラス名に基づく適切なソリューション。


[...] DWM API 呼び出しを使用するには、hwnd を渡す必要があり、タブはすべて Internet Explorer と同じハンドルを共有します。

ウィンドウ階層をどのように検査しましたか? Spy++などでIE 9 ウィンドウを検査すると、次のウィンドウ クラスの階層が表示されます(省略形)。

  • IEFrame
    • [...]
    • フレームタブ
      • [...]
    • フレームタブ
      • [...]
      • TabWindow クラス
        • シェル DocObject ビュー
          • Internet Explorer_サーバー

子ウィンドウには個別のハンドルがあるため、(私の頭の上から) FindWindowEx 関数への適切な呼び出しを介して目的のウィンドウを取得できるはずです。

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

目的のタブをすべて取得するには、FindWindowEx()hwndChildAfterの 2 番目のパラメーターを使用して結果を反復処理する必要があります。

子ウィンドウへのハンドル。検索は、Z オーダーで次の子ウィンドウから開始されます。子ウィンドウは、単なる子孫ウィンドウではなく、hwndParent の直接の子ウィンドウである必要があります。

したがって、最初にクラス「Frame Tab」を介して反復し、FindWindowEx()への 2 回目の呼び出しで各「Internet Explorer_Server」子ウィンドウを取得する必要があります (ただし、3 回目で子を上位に渡すかどうかを実験したい場合があります)。パラメータlpszClassは同等またはそれ以上の結果を生成します)。

幸運を!

于 2012-02-13T11:03:18.083 に答える
1

私が行った解決策は、Win32 API を使用することEnumWindowsでしGetWindowTextた。を使用して Internet Explorer ウィンドウを列挙しshdocvw.dll、タブのキャプションをメソッドに渡します。このメソッドは結果を解析して、GetWindowTextそのキャプションを持つウィンドウの hwnd を見つけます。

これは、タブだけでなく、すべての IE ウィンドウで機能します。

于 2012-02-18T00:36:34.200 に答える