【问题标题】:get all controls by FindWindowEx通过 FindWindowEx 获取所有控件
【发布时间】:2013-04-18 06:09:55
【问题描述】:

我正在构建一个应用程序,它将获得所有控制权到应用程序 winform 正在运行。首先,我可以将 dll 注入到 winform 正在运行的应用程序中并获取应用程序 winform 正在运行的句柄。在我让所有子窗口进入应用程序之后。接下来,我想通过 FindWindowEx 将所有控件放入子窗口。但我不能

代码如下:

static ArrayList GetAllChildrenWindowHandles(IntPtr hParent, int maxCount)
    {
        ArrayList result = new ArrayList();
        int ct = 0;
        IntPtr prevChild = IntPtr.Zero;
        IntPtr currChild = IntPtr.Zero;
        while (true && ct < maxCount)
        {
            currChild = FindWindowEx(hParent, prevChild, null, null);
            if (currChild == IntPtr.Zero)
            {
                int errorCode = Marshal.GetLastWin32Error();
                break;
            }
            result.Add(currChild);
            prevChild = currChild;
            ++ct;
        }
        return result;
    }

我得到一个子窗口的句柄并使用它作为父窗口。但是我无法通过 FindWindowEx 将所有控制权都控制到子窗口中。 对不起我的英语

【问题讨论】:

  • 如果您要查找某个特定窗口的所有子窗口,您需要EnumChildWindows
  • 逻辑结构是一棵树。最容易用递归函数遍历。但是,这当然也意味着 ArrayList 不是存储结果的合适数据结构。
  • “逻辑结构是一棵树。最容易用递归函数遍历。但是,这肯定也意味着 ArrayList 不是存储结果的正确数据结构”我也认为,但我不知道怎么做?你知道吗?谢谢:)

标签: c# c++ c hook


【解决方案1】:

您可以使用下面的代码。将其放入某个辅助类中,例如像这样使用它...

var hwndChild = EnumAllWindows(hwndTarget, childClassName).FirstOrDefault();  

如果您愿意,您可以“丢失”class 检查 - 但通常您检查的是特定目标。

您可能还想查看我发布的这篇文章 - 正在使用 此方法将焦点设置在远程窗口上(这些场景是 很常见,你迟早会遇到这个障碍)。
Pinvoke SetFocus to a particular control

public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static public extern IntPtr GetClassName(IntPtr hWnd, System.Text.StringBuilder lpClassName, int nMaxCount);

private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
    GCHandle gch = GCHandle.FromIntPtr(pointer);
    List<IntPtr> list = gch.Target as List<IntPtr>;
    if (list == null)
        throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
    list.Add(handle);
    return true;
}

public static List<IntPtr> GetChildWindows(IntPtr parent)
{
    List<IntPtr> result = new List<IntPtr>();
    GCHandle listHandle = GCHandle.Alloc(result);
    try
    {
        Win32Callback childProc = new Win32Callback(EnumWindow);
        EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
    }
    finally
    {
        if (listHandle.IsAllocated)
            listHandle.Free();
    }
    return result;
}

public static string GetWinClass(IntPtr hwnd)
{
    if (hwnd == IntPtr.Zero)
        return null;
    StringBuilder classname = new StringBuilder(100);
    IntPtr result = GetClassName(hwnd, classname, classname.Capacity);
    if (result != IntPtr.Zero)
        return classname.ToString();
    return null;
}

public static IEnumerable<IntPtr> EnumAllWindows(IntPtr hwnd, string childClassName)
{
    List<IntPtr> children = GetChildWindows(hwnd);
    if (children == null)
        yield break;
    foreach (IntPtr child in children)
    {
        if (GetWinClass(child) == childClassName)
            yield return child;
        foreach (var childchild in EnumAllWindows(child, childClassName))
            yield return childchild;
    }
}

【讨论】:

  • 不行,我可以把所有控件放到应用程序winform运行的子窗口中。我只能获得子窗口,但无法将所有控件都放入子窗口。
  • 可行 - 尝试 Spy++(或 this)进行测试 - 查看完全相同的代码 here(并确保加载所有内容,给它时间)。并从“SetFocus”链接尝试我的建议(附加到“线程”)。如果您的控件是non-standard(非 Windows),它将无法工作。并删除.FirstOrDefault() 当然:)
  • 我收到错误“找不到类型或命名空间名称'Win32Callback'(您是否缺少 using 指令或程序集引用?)”
【解决方案2】:

尝试 Spy++ 并查看您尝试枚举的控件是否为窗口。 如果它们不是窗口,则无法使用此 API 枚举它们。

【讨论】:

  • Spy++显示的控件怎么可能不是窗口?
  • @WernerHenze:这就是使用 Spy++ 的意义所在。问题中的代码可能会失败,因为控件不是窗口,但在这种情况下,Spy++ 会以同样的方式失败。 IE。我们使用 Spy++ 来建立正确的行为。
  • @MSalters:例如,您正在谈论一个父窗口,该窗口正在其客户区域中绘制一些看起来像控件并处理鼠标单击的东西,因此它的作用就像一个控件,但实际上它是不是一个真正的窗口,它只是从用户的角度来看的一个窗口!?
  • @WernerHenze:是的,就像 Internet Explorer 一样。
  • 所以 - 我使用了 Spy++ 并确定我需要获取的文本本身不是控件(或“窗口”),但我可以获得它的父窗口。是否有一个 API 可以用来以某种方式查询此文本!?
猜你喜欢
  • 2014-11-01
  • 2015-05-08
  • 2010-10-12
  • 2011-03-03
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-25
相关资源
最近更新 更多