×
您的位置: 首页 > 编程笔记

通过FindWindowEx获取所有控件(get all controls by FindWindowEx)

WinForm 时间:2020-06-15  查看:401   收藏

I am building an applicaton, It will get all control have into application winform is running. First, I can inject dll into application winform is running and get handle of application winform is running. After I get all child window into applcation. Next, I want get all controls into child window by FindWindowEx. But I can't

Here is code :

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

I get a handle of child window  and use it is parent. But I can't get all control into child window by FindWindowEx . Sorry for my english

解决方案

You can use the code below. Put it into a helper class somewhere, and e.g. use it like this...

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

You can 'lose' the class check if you wish - but usually you're checking for a specific target.

You may also wanna check this post I made a while go - which is using  this method to set a focus on a remote window (and those scenarios are  quite common, and you'll hit that snag sooner or later).
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正在运行。首先,我可以注入dll到应用程序winform正在运行,并获得应用程序winform正在运行的句柄。后我得到所有的孩子窗口进入应用。接下来,我想通过FindWindowEx将所有控件都放到子窗口中。但我不能



这里是代码:



  GetAllChildrenWindowHandles(IntPtr hParent,int maxCount)
 {
 ArrayList result = new ArrayList(); 
 intct = 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的所有控制到子窗口。
对不起我的英语


解决方案

您可以使用下面的代码。把它放在一个帮助类的某个地方,使用它像这样...



  var hwndChild = EnumAllWindows(hwndTarget,childClassName).FirstOrDefault



您可以'输掉' class 如果你愿意 - 但通常你正在检查一个特定的目标。




您可能也想检查这篇文章我做了一段时间 - 这是使用
此方法设置一个焦点远程窗口(这些情况是
很常见,你会迟早击中那个钩子)。

Pinvoke SetFocus到特定控件




  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&gt ;; 
 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子进程)
 {
 if(GetWinClass(child)== childClassName)
 yield return child; 
 foreach(var childchild in EnumAllWindows(child,childClassName))
 yield return childchild; 
} 
}


 

0% (0)
0% (0)