2010-05-02 13 views
2

Je veux écrire une application qui surveillera le contenu de tous les onglets ouverts dans IE/FireFox et déclenchera l'événement une fois que des données particulières seront affichées dans l'onglet.Mettre l'accent sur un onglet particulier dans IE et/ou FireFox

Je voudrais savoir s'il y a une API pour IE/FF pour mettre au point un TAB particulier, de sorte qu'une fois qu'un événement est déclenché, je mets le focus sur un onglet approprié.

Merci à l'avance

Répondre

0

Vous allez devoir écrire un ajout. Les onglets ressemblent à des fenêtres au contenu, vous pouvez donc utiliser un objet DOM Window pour découvrir des informations sur l'onglet en cours et faire certaines choses - close(), focus(), resizeTo() etc. Le problème est Firefox et d'autres Le navigateur moderne supprime ou ignore certains de ces événements en raison du comportement de blocage des fenêtres par défaut. En outre, le contenu ne peut pas indiquer le nombre d'onglets ouverts ou ceux qui s'exécutent pour des raisons de sécurité, il n'y aurait donc aucun moyen de les interroger par exemple. Le meilleur que vous pouvez faire est appelez window.opener d'une fenêtre pour découvrir quel autre l'a ouvert. La seule façon d'obtenir un accès complet est d'écrire un module complémentaire. Chaque navigateur a sa propre façon d'écrire des ajouts, dont certains seront plus faciles à écrire que d'autres.

1

Malheureusement, il n'y a pas d'API spécifique pour activer l'onglet ou le mettre au point.

Ci-dessous est un code comment vous pouvez activer l'onglet, mais il est seulement IE spécifique!

using System; 
using System.Collections.Generic; 
using System.Runtime.InteropServices; 
using Accessibility; 

namespace IETabsInteraction 
{ 
    internal class TabActivator 
    { 
     #region Nested type: OBJID 

     private enum OBJID : uint 
     { 
      OBJID_WINDOW = 0x00000000, 
     } 

     #endregion 

     #region Declarations 

     private const int CHILDID_SELF = 0; 
     private readonly IntPtr _hWnd; 
     private IAccessible _accessible; 

     [DllImport("oleacc.dll")] 
     private static extern int AccessibleObjectFromWindow(IntPtr hwnd, uint id, ref Guid iid, 
                  [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object 
                   ppvObject); 

     [DllImport("user32.dll", SetLastError = true)] 
     private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, 
                string lpszWindow); 

     [DllImport("oleacc.dll")] 
     private static extern int AccessibleChildren(IAccessible paccContainer, int iChildStart, int cChildren, 
                [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] object[] rgvarChildren, out int pcObtained); 

     #endregion 

     #region Constructors 

     internal TabActivator(IntPtr ieHandle) 
     { 
      _hWnd = ieHandle; 
      AccessibleObjectFromWindow(GetDirectUIHWND(ieHandle), OBJID.OBJID_WINDOW, ref _accessible); 

      CheckForAccessible(); 
     } 

     private TabActivator(IAccessible acc) 
     { 
      if (acc == null) 
       throw new Exception("Could not get accessible"); 

      _accessible = acc; 
     } 

     #endregion 

     private TabActivator[] Children 
     { 
      get 
      { 
       var num = 0; 
       var res = GetAccessibleChildren(_accessible, out num); 

       if (res == null) 
        return new TabActivator[0]; 

       var list = new List<TabActivator>(res.Length); 

       foreach (object obj in res) 
       { 
        var acc = obj as IAccessible; 

        if (acc != null) 
         list.Add(new TabActivator(acc)); 
       } 

       return list.ToArray(); 
      } 
     } 

     private int ChildCount 
     { 
      get { return _accessible.accChildCount; } 
     } 

     /// <summary> 
     /// Gets LocationUrl of the tab 
     /// </summary> 
     private string LocationUrl 
     { 
      get 
      { 
       var url = _accessible.accDescription[CHILDID_SELF]; 

       if (url.Contains(Environment.NewLine)) 
        url = url.Split('\n')[1]; 

       return url; 
      } 
     } 

     private void CheckForAccessible() 
     { 
      if (_accessible == null) 
       throw new Exception("Could not get accessible. Accessible can't be null"); 
     } 

     internal void ActivateByTabsUrl(string tabsUrl) 
     { 
      var tabIndexToActivate = GetTabIndexToActivate(tabsUrl); 

      AccessibleObjectFromWindow(GetDirectUIHWND(_hWnd), OBJID.OBJID_WINDOW, ref _accessible); 

      CheckForAccessible(); 

      var index = 0; 
      var ieDirectUIHWND = new TabActivator(_hWnd); 

      foreach (var accessor in ieDirectUIHWND.Children) 
      { 
       foreach (var child in accessor.Children) 
       { 
        foreach (var tab in child.Children) 
        { 
         if (tabIndexToActivate >= child.ChildCount - 1) 
          return; 

         if (index == tabIndexToActivate) 
         { 
          tab.ActivateTab(); 
          return; 
         } 

         index++; 
        } 
       } 
      } 
     } 

     private void ActivateTab() 
     { 
      _accessible.accDoDefaultAction(CHILDID_SELF); 
     } 

     private int GetTabIndexToActivate(string tabsUrl) 
     { 
      AccessibleObjectFromWindow(GetDirectUIHWND(_hWnd), OBJID.OBJID_WINDOW, ref _accessible); 

      CheckForAccessible(); 

      var index = 0; 
      var ieDirectUIHWND = new TabActivator(_hWnd); 

      foreach (var accessor in ieDirectUIHWND.Children) 
      { 
       foreach (var child in accessor.Children) 
       { 
        foreach (var tab in child.Children) 
        { 
         var tabUrl = tab.LocationUrl; 

         if (!string.IsNullOrEmpty(tabUrl)) 
         { 
          if (tab.LocationUrl.Contains(tabsUrl)) 
           return index; 
         } 

         index++; 
        } 
       } 
      } 

      return -1; 
     } 

     private IntPtr GetDirectUIHWND(IntPtr ieFrame) 
     { 
      // For IE 8: 
      var directUI = FindWindowEx(ieFrame, IntPtr.Zero, "CommandBarClass", null); 
      directUI = FindWindowEx(directUI, IntPtr.Zero, "ReBarWindow32", null); 
      directUI = FindWindowEx(directUI, IntPtr.Zero, "TabBandClass", null); 
      directUI = FindWindowEx(directUI, IntPtr.Zero, "DirectUIHWND", null); 

      if (directUI == IntPtr.Zero) 
      { 
       // For IE 9: 
       //directUI = FindWindowEx(ieFrame, IntPtr.Zero, "WorkerW", "Navigation Bar"); 
       directUI = FindWindowEx(ieFrame, IntPtr.Zero, "WorkerW", null); 
       directUI = FindWindowEx(directUI, IntPtr.Zero, "ReBarWindow32", null); 
       directUI = FindWindowEx(directUI, IntPtr.Zero, "TabBandClass", null); 
       directUI = FindWindowEx(directUI, IntPtr.Zero, "DirectUIHWND", null); 
      } 

      return directUI; 
     } 

     private static int AccessibleObjectFromWindow(IntPtr hwnd, OBJID idObject, ref IAccessible acc) 
     { 
      var guid = new Guid("{618736e0-3c3d-11cf-810c-00aa00389b71}"); // IAccessibleobject obj = null; 
      object obj = null; 

      var num = AccessibleObjectFromWindow(hwnd, (uint) idObject, ref guid, ref obj); 

      acc = (IAccessible) obj; 

      return num; 
     } 

     private static object[] GetAccessibleChildren(IAccessible ao, out int childs) 
     { 
      childs = 0; 
      object[] ret = null; 
      var count = ao.accChildCount; 

      if (count > 0) 
      { 
       ret = new object[count]; 
       AccessibleChildren(ao, 0, count, ret, out childs); 
      } 

      return ret; 
     } 
    } 
} 

Oui, beaucoup de lignes pour une tâche simple :)

Pour l'exécuter, vous aurez besoin:

var ie = new ShellWindows(); 

// check if ie is open and get first tab of the ie 
if (ie.Count > 0) 
{  
    var hWnd = (IntPtr)ie.Item(0).HWND; 
    new TabActivator(hWnd).ActivateByTabsUrl("www.stackoverflow.com"); 
} 

Ce jeux de codes focus sur l'onglet avec l'URL spécifique , mais vous pouvez le changer pour activer l'onglet avec un titre spécifique, etc.

+0

Je sais que c'est une question un peu ancienne, mais j'ai trouvé votre réponse avec google. J'essaye de l'implémenter pour IE8 et IE9, mais j'obtiens une erreur dans 'LocationURL' dans la ligne' var url = _accessible.accDescription [CHILDID_SELF]; '. Erreur: 'Propriété, indexeur ou événement 'accDescription' n'est pas supporté par le langage; essayez d'appeler directement la méthode accesseur 'Accessibility.IAccessible.get_accDescription (object) '. J'utilise .NET 3.5 cela peut être le problème? Cela peut-il être réparé? Je voudrais vraiment utiliser votre solution :) – Misiu

+0

Cela semble être le seul moyen d'activer un onglet. Dans mon expérience, si l'utilisateur a désactivé la navigation par tabulation dans IE, alors ce code est en quelque sorte «bloqué», mais finalement jette l'erreur. Je vérifie d'abord dans le registre si la navigation par onglet est activée avant de l'utiliser. – darbid