查找包含特定文本的窗口
我试图找出一个特定的窗口是否已经被一个Process打开。 该过程会产生多个窗口,我需要检查它们。
我不难发现这个过程
foreach (Process p in Process.GetProcesses())
{
if (p.MainModule.FileName.ToLower().EndsWith("foo.exe"))
FindChildWindowWithText(p); //do work
问题是接下来要做什么。 我无法使用MainWindowText
,因为它随着激活的窗口而改变。
然后我尝试使用Windows函数EnumChildWindows
和GetWindowText
,但我不确定是否将正确的句柄传递给EnumChildWindows。 EnumChildWindows
在通过MainWindowHandle时按预期工作,但当然MainWindowHandle随活动窗口而变化。 所以我通过Process.Handle
,但切换应用程序的窗口时会得到不同的句柄和不同的结果。 (据我所知,EnumChildWindows不仅可以处理窗口,而且可以在.net中使用控件进行操作,如果我也可以获取窗口的标题,那么这也不成问题)
也许我这样做的方式是错误的,我需要一种不同的方法 - 再一次,我的问题就像找到一个符合特定正则表达式的文本一样简单。 所以我可能需要一个枚举所有窗口的功能,这在任务栏中都是可见的。
谢谢
一旦你有了进程,你可以枚举进程中的所有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?
链接地址: http://www.djcxy.com/p/38835.html上一篇: Find window with specific text for a Process
下一篇: How do I convert a RACSignal to a SignalProducer in ReactiveCocoa 5?