查找具有Process的特定文本的窗口

Axa*_*dax 9 .net c# windows pinvoke process

我试图找出一个具有特定功能的窗口是否已被进程打开.这个过程产生了多个窗口,我需要检查它们.

我毫不费力地找到了这个过程

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

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

然后我试图使用Windows函数EnumChildWindowsGetWindowText,但我不知道如果我传递一个正确的句柄EnumChildWindows.在EnumChildWindows通过MainWindowHandle的时候,但当然,MainWindowHandle与活动窗口的变化按预期工作.所以我通过了Process.Handle,但是在切换应用程序的窗口时,我得到了不同的句柄和不同的结果.(据我所知,EnumChildWindows返回的句柄,不仅窗户,但控制在.NET讲,这是没有问题的,如果我能得到窗口的标题太)

也许我这样做是错误的,我需要一个不同的方法 - 再次,我的问题就像找到一个文本与特定正则表达式匹配的窗口一样简单.所以我可能需要一个枚举所有窗口的函数,这些窗口在任务栏中都是可见的.

谢谢

Chr*_*lor 21

完成Process后,您可以枚举流程中的所有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);
Run Code Online (Sandbox Code Playgroud)

以下是一对可用于在特定过程中查找窗口的函数的示例,我从您的问题中了解到您有过程,问题是枚举窗口.

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;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以调用FindWindowInProcess函数来查找标题以"ABC"结尾的窗口作为示例.

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

当然你可以用任何满足你的窗口搜索条件的表达式替换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;
}
Run Code Online (Sandbox Code Playgroud)