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函数EnumChildWindows和GetWindowText,但我不知道如果我传递一个正确的句柄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)