FindWindowEx on child dialog window

Rita picture Rita · May 23, 2013 · Viewed 8.4k times · Source

I'm trying to get the handle of a child dialog window. I've tried using FindWindowEx, but it didn't work. Instead, FindWindow did work.

I did an experiment with visual studio's options window, with the following code:

IntPtr vsHandle = Process.GetProcessById(vsProcessId).MainWindowHandle; // consistent with spy++'s parent handle of options window

IntPtr optionsHandle = FindWindowEx(vsHandle, IntPtr.Zero, "#32770", "Options"); // returns 0

IntPtr optionsHandle2 = FindWindow("#32770", "Options"); // returns correct handle

From my understanding, FindWindowEx should've worked, it is a child window.

I'm running windows xp, and have also tried using FindWindowEx(vsHandle, IntPtr.Zero, "#32770", null). Didn't work. Seems like the only way to get it is using FindWindow which isn't good enough as two parent instances with the same dialog can be open.

This is the declaration:

[DllImport("user32.dll")]
Private static extern IntPtr FindWindow(string className, string windowTitle);
[DllImport("user32.dll")]
Private static extern IntPtr FindWindowEx(IntPtr parentHWnd, IntPtr childAfterHWnd,     string className, string windowTitle);

Thanks in advance.

Answer

Rita picture Rita · Jun 5, 2013

I found a solution to this. The reason FindWindowEx didn't work was because it only works on child windows that have WS_CHILD style, and apparently dialog windows do not have this style. It is why EnumChildWindows won't work either (I've tried).

So the ugly solution is EnumWindows combined with GetParent to compare the handle and the text.

        struct SearchData
        {
            public string WindowText;
            public IntPtr ParentHandle;
            public IntPtr ResultHandle;
        }

        delegate bool EnumWindowsCallback(IntPtr currentWindowHandle, ref SearchData searchData);

        [DllImport("user32.dll")] static extern bool EnumWindows(EnumWindowsCallback callback, ref SearchData searchData);

        [DllImport("user32.dll")] static extern IntPtr GetParent(IntPtr childHandle);

        [DllImport("user32.dll")] static extern void GetWindowText(IntPtr handle, StringBuilder resultWindowText, int maxTextCapacity);


        static bool Callback(IntPtr currentWindowHandle, ref SearchData searchData)
        {
            bool continueEnumeration = true;

            IntPtr currentWindowParentHandle = GetParent(currentWindowHandle);

            if (currentWindowParentHandle == searchData.ParentHandle)
            {
                var windowText = new StringBuilder(1024);
                GetWindowText(currentWindowHandle, windowText, windowText.Capacity);

                if (windowText.ToString() == searchData.WindowText)
                {
                    searchData.ResultHandle = currentWindowHandle;
                    continueEnumeration = false;
                }
            }

            return continueEnumeration;
        }


        IntPtr GetChildWindowHandle(string windowText, IntPtr parentHandle)
        {
            var searchData = new SearchData{ParentHandle=parentHandle, WindowText=windowText};

            EnumWindows(Callback, ref searchData);

            return searchData.ResultHandle;
        }