突然の Win32 ネタです。
トップレベルウィンドウを列挙する場合、 EnumWindows
を使うのですが、
そのとき、見えないウィンドウなども混ざってしまいます。
そういうのを除外する方法です。
コードはこんな感じ。
NativeMethods.EnumWindows((hWnd, lParam) => { // WS_VISIBLE でない if (!NativeMethods.IsWindowVisible(hWnd)) return true; // タイトル空 var title = new StringBuilder(1024); NativeMethods.GetWindowText(hWnd, title, title.Capacity); if (string.IsNullOrWhiteSpace(title.ToString())) return true; // Skipped // UWP NativeMethods.DwmGetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.Cloaked, out var isCloaked, Marshal.SizeOf(typeof(bool))); if (isCloaked) return true; // ここが見えるウィンドウ return true; }, IntPtr.Zero);
で、問題の見えないウィンドウなんですが、タスクマネージャを開くと分かるのですが、
Windows 10 の場合、いくつかの UWP アプリはバックグラウンドプロセスとして動作しており、
それらは見えないながらも、トップレベルウィンドウとして存在しています。
例えば、起動していなくても「設定」「Microsoft Edge」は普通に取得できてしまいます。
また、それらのアプリは IsWindowVisible
で除外することもできません。
そういうときに使うのが、DwmGetWindowAttribute
です。
第 2 引数に DWMWA_CLOAKED
を指定し、第 3 引数に入れられた値を見ることで、除外できます。
ということで、除外する方法でした。
(NativeMethods
の部分は、 pinvoke.net からコピーしてくれば良いと思います。)