【问题标题】:Find window with specific text for a Process查找带有进程特定文本的窗口
【发布时间】:2010-04-27 08:30:33
【问题描述】:

我正在尝试查找特定的窗口是否已被进程打开。该过程会产生多个窗口,我需要全部检查。

我很容易找到过程,

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 不仅将句柄返回给 windows,而且 .net 中的 controls 说话,如果我也可以获得窗口的标题,那没问题)

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

谢谢

【问题讨论】:

    标签: c# .net windows process pinvoke


    【解决方案1】:

    一旦你有了进程,你就可以枚举进程中的所有窗口并测试它们是否与你正在寻找的窗口匹配。

    您将需要以下 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);
    

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

    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;
    }
    

    【讨论】:

    • In FindChildWindow ...在检查compareTitle的结果后,不应该是hChildWnd而不是hWnd吗?
    【解决方案2】:

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    • 1970-01-01
    相关资源
    最近更新 更多