0

I create a WinForms application that consist of two forms (MainForm and SecondForm). When the application is executed, there will be three forms on screen.

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        var firstChildForm = new SecondForm();
        firstChildForm.Text = "First child";
        firstChildForm.Show();  
        firstChildForm.StartPosition = FormStartPosition.Manual;

        var secondChildForm = new SecondForm();
        secondChildForm.Text = "Second child";
        secondChildForm.StartPosition = FormStartPosition.CenterScreen;
        secondChildForm.Show(); 
    }
}

How can I use a separate application that lists the titles of children forms for the main form ("ThreeForms")? I can only get the title and handle of the parent.

    private void button1_Click(object sender, EventArgs e)
    {
        Process[] processes = System.Diagnostics.Process.GetProcessesByName("ThreeForms");
        foreach (Process p in processes)
        {
            IntPtr parentHandle = p.MainWindowHandle; // this is found
            listBox1.Items.Add("Parent Handle: " + parentHandle.ToString());
            List<IntPtr> childrenHandles = GetChildWindows(parentHandle); // empty list

            foreach(var ptr in childrenHandles)
            {
                listBox1.Items.Add(ptr.ToString());
            }
        }
    }
    public 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;
    }
    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);
        //  You can modify this to check to see if you want to cancel the operation, then return a null here
        return true;
    }
Nick_F
  • 1,103
  • 2
  • 13
  • 30
  • 1
    The two other Forms are not *child Forms*, those are all top-level Windows. -> UIAutomation's `RootElement` / `EnumThreadWindows()` – Jimi May 28 '22 at 06:27
  • But if I use Process[] processes = Process.GetProcesses(); the two other forms ("First child" and "Second child") are not listed. I can only see "ThreeForms" in the processes. If I use Task Manager, I can see all three forms listed under "ThreeForms" process. – Nick_F May 28 '22 at 06:31
  • 1
    The other two top-level Windows belong to the same Process; the Process class only references the current `MainWindowHandle`. – Jimi May 28 '22 at 06:35
  • Thanks for pointing me in the right direction, I found a sample that displays all windows, at https://stackoverflow.com/questions/41928549/c-sharp-trying-to-enumerate-every-window-for-each-process-thread – Nick_F May 28 '22 at 06:40
  • [How to enumerate all windows belonging to a particular process using .NET?](https://stackoverflow.com/q/2531828/7444103) - This one actually contains answers. Mark as duplicate? – Jimi May 28 '22 at 06:43
  • Yes, you can mark it as a duplicate. Thanks for help – Nick_F May 28 '22 at 06:44

0 Answers0