|
■No101187 (魔界の仮面弁士) に追記 > Process クラスの MainWindowHandle プロパティは 非表示ウィンドウを捉えられない(Zero を返す)仕様ですから > EnumWindows API などで拾うか、プロセス間通信でハンドルを伝えているのものと推察しますが…。
トップレベル ウィンドウのハンドルを得るのであれば、 EnumWindows API よりも、FindWindowEx API の方が良さそうです。
[DllImport("user32", CharSet = CharSet.Auto)] private static extern IntPtr FindWindowEx(IntPtr parentWnd, IntPtr previousWnd, string className, string windowText);
フォームを非表示にする際に、その非表示フォームの Text に識別用の文字列をセットしておけば、 後から探索する側は、 IntPtr targetWindow = FindWindowEx(IntPtr.Zero, IntPtr.Zero, null, 識別用の文字列); で取得できるかと思います。 ※識別に使うタイトル文字列は、他と被らない名前を用意する必要があります。
あるいは識別情報を入れておかずに、ウィンドウを全列挙して調べるという事もできますが、 何らかの識別情報が無いと判断し辛いと思います。(アプリには Form 以外の非表示ウィンドウも含まれるので…)
一応、その列挙版も作ってみました。
/// <summary> /// 自分と同じ名前のプロセスを列挙します。(自分自身は含みません) /// </summary> public static TopLevelWindow[] GetOtherProcesses() { var topLevelWindows = new List<TopLevelWindow>();
var p = Process.GetCurrentProcess(); var pid = p.Id; // 自プロセス以外のプロセス ID を列挙 var procList = Process.GetProcessesByName(p.ProcessName).Select(x => x.Id).Where(x => x != pid).ToList();
IntPtr hWnd = IntPtr.Zero; while (IntPtr.Zero != (hWnd = FindWindowEx(IntPtr.Zero, hWnd, null, null))) { var w = new TopLevelWindow(hWnd); if (procList.Contains(w.ProcessId)) { topLevelWindows.Add(w); } } return topLevelWindows.ToArray(); }
[DllImport("user32", CharSet = CharSet.Auto)] private static extern IntPtr FindWindowEx(IntPtr parentWnd, IntPtr previousWnd, string className, string windowText);
public class TopLevelWindow { public IntPtr WindowHandle { get; } public string WindowText { get; } public int ProcessId { get; } public int OwnerThreadId { get; } public string ClassName { get; } public TopLevelWindow(IntPtr hWnd) { WindowHandle = hWnd; int processId; OwnerThreadId = GetWindowThreadProcessId(hWnd, out processId); ProcessId = processId; var sb = new StringBuilder(257); GetClassName(hWnd, sb, sb.Capacity); ClassName = sb.ToString(); sb = new StringBuilder(GetWindowTextLength(hWnd) + 1); GetWindowText(hWnd, sb, sb.Capacity); WindowText = sb.ToString(); } [DllImport("user32")] private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
[DllImport("user32", CharSet = CharSet.Auto)] private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32", CharSet = CharSet.Auto)] public static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32", CharSet = CharSet.Auto)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); }
|