Programming

表示されているウィンドウのRectを上から順に取得したい

 備忘録シリーズという事で、上記の事をする必要があったんですが、こちらの実装方法をメモっときます。まずは使用するDllの宣言です

[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowInfo(IntPtr hwnd, ref WINDOWINFO pwi);

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetTopWindow(IntPtr hWnd);

[DllImport("user32.dll", SetLastError = true)]
 public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);

[DllImport("dwmapi.dll")]
private static extern int DwmGetWindowAttribute(IntPtr hWnd, DWMWINDOWATTRIBUTE dwAttribute, out RECT pvAttribute, int cbAttribute);

[DllImport("dwmapi.dll")]
private static extern int DwmGetWindowAttribute(IntPtr hWnd, DWMWINDOWATTRIBUTE dwAttribute, out bool pvAttribute, int cbAttribute);


次は実装方法です。GetTopWindowで最初にウィンドウのハンドルを取得して、GetWindow(hWnd, GW_HWNDNEXT)で順に取得すると上から順にウィンドウ情報が取得出来ます。次にGetWindowInfoでウィンドウの情報を取得して要らないものを省くんですが、これだけだとバックグラウンドで動いている(電卓とか設定とか)も拾ってしまい、またGetWindowInfoで取得されるRectは若干実際とずれてるんですよね。そんな時は、DwmGetWindowAttributeを使うらしいです。これはハマった。まじハマりましたが出来て良かった^^

        const uint WS_VISIBLE = 0x10000000;
        const uint WS_DISABLED = 0x08000000;
        const uint GW_HWNDNEXT = 2;

        static public List<RECT>GetWindowsRectInfo()
        {
            //表示されている順番にRECT情報をリストに格納する
            var list = new List<RECT>();

            var hWnd = GetTopWindow(IntPtr.Zero);
            do
            {
                WINDOWINFO wi = new WINDOWINFO();
                wi.cbSize = Marshal.SizeOf(wi);
                int retCode = GetWindowInfo(hWnd, ref wi);

                if (retCode <= 0)
                    continue;

                if ((wi.dwStyle & WS_VISIBLE) == 0)
                    continue;

                if ((wi.dwStyle & WS_DISABLED) == WS_DISABLED)
                    continue;

                if (wi.cyWindowBorders == 0)
                    continue;

                //バックグランドなのかを判定
                bool isLock = false;
                retCode = DwmGetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAKED, out isLock, Marshal.SizeOf(typeof(bool)));

                if (retCode >= 0 && isLock == false)
                {
                    //ウィンドウの見た目通りのRectを取得したい
                    //WINDOWSINFOのrcWindowだと実際のサイズより大きい
                    RECT rc = new RECT();
                    DwmGetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, out rc, Marshal.SizeOf(typeof(RECT)));

                    list.Add(rc);
                }

            } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != IntPtr.Zero);

            return list;
        }

しかし、まだまだuser32の関数を使う機会って結構ありますね。。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

PAGE TOP