查找包含特定文本的窗口

我试图find一个特定的窗口是否已被一个进程打开。 该过程会产生多个窗口,我需要检查所有的窗口。

我不难find这个过程

foreach (Process p in Process.GetProcesses()) { if (p.MainModule.FileName.ToLower().EndsWith("foo.exe")) FindChildWindowWithText(p); //do work 

问题是接下来要做什么。 我不能使用Process的MainWindowText ,因为它随着激活的窗口而改变。

然后我试图使用Windows函数EnumChildWindowsGetWindowText ,但我不知道如果我传递一个正确的句柄EnumChildWindows。 EnumChildWindows在通过MainWindowHandle时按预期工作,但当然MainWindowHandle随活动窗口而变化。 所以我通过Process.Handle ,但是当切换应用程序的窗口时,我得到了不同的句柄和不同的结果。 (据我所知,EnumChildWindows不仅返回句柄,而且还包括.NET中的控件 ,如果我能得到窗口的标题也不会有问题)

也许我正在做这个错误的方式,我需要一个不同的方法 – 我的问题再一次find一个与特定的正则expression式匹配的文本的窗口。 所以我可能需要一个枚举所有窗口的function,在任务栏中可见等等。

谢谢

一旦你有进程,你可以枚举过程中的所有Windows,并测试它们中的任何一个匹配你正在寻找的窗口。

您将需要以下P / Invoke声明

 [DllImport("user32", SetLastError=true)] [return: MarshalAs(UnmanagedType.Bool)] private extern static bool EnumThreadWindows(int threadId, EnumWindowsProc callback, IntPtr lParam); [DllImport("user32", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); [DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)] private extern static int GetWindowText(IntPtr hWnd, StringBuilder text, int maxCount); 

followng是一对函数的例子,可以用来在特定的过程中找到窗口,我从你的问题中了解到你有Process,问题是枚举窗口。

 public static IntPtr FindWindowInProcess(Process process, Func<string, bool> compareTitle) { IntPtr windowHandle = IntPtr.Zero; foreach (ProcessThread t in process.Threads) { windowHandle = FindWindowInThread(t.Id, compareTitle); if (windowHandle != IntPtr.Zero) { break; } } return windowHandle; } private static IntPtr FindWindowInThread(int threadId, Func<string, bool> compareTitle) { IntPtr windowHandle = IntPtr.Zero; EnumThreadWindows(threadId, (hWnd, lParam) => { StringBuilder text = new StringBuilder(200); GetWindowText(hWnd, text, 200); if (compareTitle(text.ToString())) { windowHandle = hWnd; return false; } return true; }, IntPtr.Zero); return windowHandle; } 

然后你可以调用FindWindowInProcess函数来查找标题以“ABC”结尾的窗口为例。

 IntPtr hWnd = FindWindowInProcess(p, s => s.EndsWith("ABC")); if (hWnd != IntPtr.Zero) { // The window was found.... } 

当然,你可以用满足你窗口搜索条件的表达式替换s => s.EndsWith(“ABC”),它可以是一个正则表达式等等。

这里也是FindThreadWindow的一个版本,它也会检查第一级的子窗口。 如果您的窗口在层次结构中更深入,则可以进一步采用这种方法并使其成为递归函数。

 private static IntPtr FindWindowInThread(int threadId, Func<string, bool> compareTitle) { IntPtr windowHandle = IntPtr.Zero; EnumThreadWindows(threadId, (hWnd, lParam) => { StringBuilder text = new StringBuilder(200); GetWindowText(hWnd, text, 200); if (compareTitle(text.ToString())) { windowHandle = hWnd; return false; } else { windowHandle = FindChildWindow(hWnd, compareTitle); if (windowHandle != IntPtr.Zero) { return false; } } return true; }, IntPtr.Zero); return windowHandle; } private static IntPtr FindChildWindow(IntPtr hWnd, Func<string, bool> compareTitle) { IntPtr windowHandle = IntPtr.Zero; EnumChildWindows(hWnd, (hChildWnd, lParam) => { StringBuilder text = new StringBuilder(200); GetWindowText(hChildWnd, text, 200); if (compareTitle(text.ToString())) { windowHandle = hChildWnd; return false; } return true; }, IntPtr.Zero); return windowHandle; } 

而不是枚举进程和找到窗口,我会枚举窗口(使用EnumWindows ),并找到进程(使用GetGuiThreadInfo )。

几乎类似的(或者是完全一样的?)问题与接受的答案,你可以参考: .NET(C#):获取子窗口,当你只有一个进程句柄或PID?