我试图找到一个具有特定的窗口是否已被一个进程打开.该进程产生多个窗口,我需要检查它们.
我没有找到这个过程的麻烦
foreach (Process p in Process.GetProcesses()) { if (p.MainModule.FileName.ToLower().EndsWith("foo.exe")) FindChildWindowWithText(p); //do work
问题是下一步该做什么.我不能使用Process’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,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,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的版本,它也将检查子窗口的第一级.如果您的Windows在层次结构中更深一些,您可以进一步将其作为递归函数.
private static IntPtr FindWindowInThread(int threadId,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,bool> compareTitle) { IntPtr windowHandle = IntPtr.Zero; EnumChildWindows(hWnd,(hChildWnd,lParam) => { StringBuilder text = new StringBuilder(200); GetWindowText(hChildWnd,200); if (compareTitle(text.ToString())) { windowHandle = hChildWnd; return false; } return true; },IntPtr.Zero); return windowHandle; }