sd_dracula
sd_dracula

Reputation: 3896

Get Internet Explorer tab title

I am trying to get a list of all the open IE tab titles or search for a specific tab title.

I've been using this but does not work for every tab for some reason:

// Get a handle to an application window.
    [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindWindow(string lpClassName,
        string lpWindowName);

IntPtr explorerHandle = FindWindow("IEFrame", "Google - Internet Explorer");

        // Verify that we found the Window.
        if (explorerHandle == IntPtr.Zero)
        {
            MessageBox.Show("Didn't find an instance of IE");
            return;
        }

I am particularly looking for tabs which have "This page can’t be displayed" in the title.

Any suggestions?

Upvotes: 2

Views: 2752

Answers (1)

Quentin Roger
Quentin Roger

Reputation: 6538

The last time I needed to do something like that I used this code: (It's working !)

    [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);

    [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindWindow(string lpClassName,
      string lpWindowName);

    public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
    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;
        }
    }

And to use it :

  IntPtr handle = FindWindow("IEFrame", "Google");
  var hwndChilds = EnumAllWindows(handle, "Frame Tab");

hwndChilds is a list of IntPtr to all of Frame Tab.

EDIT : I complete my answer with the next steps to get the title of your tabs.

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [Out] StringBuilder lParam);

    [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
    public static extern IntPtr GetParent(IntPtr hWnd);


    public static string GetWindowTextRaw(IntPtr hwnd)
        {
            uint WM_GETTEXT = 0x000D;
            uint WM_GETTEXTLENGTH = 0x000E;
            // Allocate correct string length first
            int length = (int)SendMessage(hwnd, WM_GETTEXTLENGTH, IntPtr.Zero, null);
            StringBuilder sb = new StringBuilder(length + 1);
            SendMessage(hwnd, WM_GETTEXT, (IntPtr)sb.Capacity, sb);
            return sb.ToString();
        }

You can test it with :

  static void Main(string[] args)
  {
        IntPtr handle = FindWindow("IEFrame", "Google");
        var hwndChild = EnumAllWindows(handle, "Frame Tab");
        foreach (var intPtr in hwndChild)
        {
            var ptr = GetParent(intPtr);
            var text = GetWindowTextRaw(ptr);
            Console.WriteLine(text);
        }
        Console.ReadLine();        
  }

and the result :

enter image description here

If you need more explanations don't hesitate to ask. You can find all pInvoke signatures on http://www.pinvoke.net/

Have a great day !

Upvotes: 3

Related Questions