查找包含特定文本的窗口

我试图找出一个特定的窗口是否已经被一个Process打开。 该过程会产生多个窗口,我需要检查它们。

我不难发现这个过程

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

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

然后我尝试使用Windows函数EnumChildWindowsGetWindowText ,但我不确定是否将正确的句柄传递给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?