gpt4 book ai didi

c# - 通过句柄或 pid 获取窗口的子窗口

转载 作者:太空狗 更新时间:2023-10-30 01:36:26 24 4
gpt4 key购买 nike

我有主进程/窗口的句柄和pid。
我想获取进程/窗口的子项 - 只有带有标题的可 window 口。

为了实现我想要的效果,我使用了以下内容:

[DllImport("user32.dll")] private static extern int EnumWindows(EnumWindowsProc ewp, int lParam);
[DllImport("user32.dll", SetLastError = true)] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")] private static extern bool IsWindowVisible(int hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int GetWindowText(int hWnd, StringBuilder title, int size);


public delegate bool EnumWindowsProc(int hWnd, int lParam); //Delegate used for EnumWindows() callback function.


public void GetChildren()
{
//Declare a callback delegate for EnumWindows() API call.
EnumWindowsProc ewp = new EnumWindowsProc(EvalWindow);
//Enumerate all Windows.
EnumWindows(ewp, 0);
}

//EnumWindows CALLBACK function
private bool EvalWindow(int hWnd, int lParam)
{
//Get the ThreadProcessId of the Window.
IntPtr handle = (IntPtr)hWnd;
uint currentThreadPid;
GetWindowThreadProcessId(handle, out currentThreadPid);

//Check if the Window is children of the current Window (if it is, it will have the same pid).
if (currentThreadPid != _threadPid)
return true;

//Check if Window is Visible or not.
if (!IsWindowVisible(hWnd))
return true;

//Get the Window's Title.
StringBuilder title = new StringBuilder(256);
GetWindowText(hWnd, title, 256);

//Check if Window has Title.
if (title.Length == 0)
return true;

//Add new Window to the _childrenhWnd.
_childrenhWnd.Add(handle);

return true;
}

其中 _threadPid 是父进程的 pid。

效果很好,但我觉得有更好的方法来完成它,而不是遍历所有打开的窗口并过滤它们。

我说的对吗?我怎样才能做得更好?

我看到了一些关于 EnumChildWindows 的东西,但我可以实现同样的目标。

编辑:

根据 RaymondChen 的评论,我想澄清一下我说“ child ”的意思:
1. 如果您打开便签并添加便签 - 便签是子项。
2. 如果打开 Paint.NET 并按 (f5, f6, f7, f8) 打开面板 - 这些是子窗口。
程序的每个非主窗口(也包括对话框)我都称为子窗口。

编辑 2:

这是应用 Hans 方法后的代码:

[DllImport("user32.dll")] static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
[DllImport("user32.dll")] private static extern bool IsWindowVisible(int hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int GetWindowText(int hWnd, StringBuilder title, int size);


delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);


public void GetChildren()
{
foreach (ProcessThread processThread in _process.Threads)
{
EnumThreadWindows(processThread.Id,
(hWnd, lParam) =>
{
//Check if Window is Visible or not.
if (!IsWindowVisible((int)hWnd))
return true;

//Get the Window's Title.
StringBuilder title = new StringBuilder(256);
GetWindowText((int)hWnd, title, 256);

//Check if Window has Title.
if (title.Length == 0)
return true;

_childrenhWnd.Add(hWnd);

return true;
}, IntPtr.Zero);
}
}

不需要使用 GetWindowLongPtr 因为所有拥有的窗口都必须有标题并且可见,否则我真的不在乎所以这些条件已经过滤了拥有的窗口。

最佳答案

很明显,您实际上并不是在谈论子窗口,EnumWindows() 不会枚举它们。这些肯定是 拥有的窗口,它们位于其所有者之上,并在所有者最小化时最小化。用于工具窗口和对话框,如 Paint.NET 使用。没有专门的 winapi 函数来枚举拥有的窗口。

您可以提高效率。枚举进程中的线程,使用Process.Threads。然后为每个线程使用 EnumThreadWindows() .带有 GWLP_HWNDPARENT 的 GetWindowLongPtr() 返回所有者的句柄,如果它是一个拥有的窗口则为非零。

关于c# - 通过句柄或 pid 获取窗口的子窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22173915/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com