过去 5 天一直在解决这个问题,所以决定发布这个问题。
我有一个附加到 IE 工具栏的应用程序(IE Addon)。如果打开 IE 的一个实例(没有任何选项卡),则应用程序可以正常工作。但是,如果我们打开了多个选项卡,它将尝试处理所有选项卡,而不是单击按钮的选项卡。
问题是所有选项卡生成的 HWND(来自 IE.HWND)值都是相同的,包括父选项卡。
这是我在启动应用程序之前执行的检查:
Dim SWs As New SHDocVw.ShellWindows
Dim IE As SHDocVw.InternetExplorer
Dim mhWnd As Long
myhWnd = GetForegroundWindow()
For Each IE In SWs
If Strings.Left(IE.LocationURL, 4) = "http" Then 'if the document is IE then proceed because EXPLORER window returns in the same group
Set Doc = IE.document
MsgBox ("Debugging 3 IE.hwnd :" & IE.hwnd & "myHwnd : " & myhWnd)
If (IE.hwnd = myhWnd ) Then
'application launch code
每次运行上述内容时,它都会尝试处理所有打开的选项卡,相反,我只对用户当前所在的选项卡感兴趣。
尝试使用 IAccessibility 来识别当前选项卡,但 IAccessible 始终返回 null。请参阅下面的 IAccessibility 代码:
using System;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using SHDocVw;
using Accessibility;
using System.Windows.Forms;
namespace FinWindowsTab
{
public class FindWindowsTab
{
public enum OBJID : uint
{
OBJID_WINDOW = 0x00000000,
}
private const int IE_ACTIVE_TAB = 2097154;
private const int CHILDID_SELF = 0;
private IAccessible accessible;
private FindWindowsTab[] Children;
public static void Main(String[] args)
{
// InternetExplorer IE = new InternetExplorer();
ShellWindows SW = new ShellWindows();
try
{
foreach (InternetExplorer IE in SW)
{
if (IE.Name == "Windows Internet Explorer")
{
string urlOfTabToActivate = IE.LocationURL;
var directUi = GetDirectUIHWND((IntPtr)IE.HWND);
var iacc = AccessibleObjectFromWindow(directUi);
var tabRow = FindAccessibleDescendant(iacc, "Tab Row");
var tabs = AccChildren(tabRow);
int tc = tabs.Count;
int k = 0;
// walk through the tabs and tick the chosen one
foreach (var candidateTab in tabs)
{
k++;
// the last tab is "New Tab", which we don't want
if (k == tc) continue;
// the URL on *this* tab
string localUrl = UrlForTab(candidateTab);
MessageBox.Show("Local Url :" + localUrl);
// same? if so, tick it. This selects the given tab among all
// the others, if any.
if (urlOfTabToActivate != null && localUrl.Equals(urlOfTabToActivate))
{
candidateTab.accDoDefaultAction(0);
return;
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show("An exception has occured : " + ex.Message);
}
}
private static IntPtr GetDirectUIHWND(IntPtr ieFrame)
{
// try IE 9 first:
IntPtr intptr = FindWindowEx(ieFrame, IntPtr.Zero, "WorkerW", null);
if (intptr == IntPtr.Zero)
{
// IE8 and IE7
intptr = FindWindowEx(ieFrame, IntPtr.Zero, "CommandBarClass", null);
}
intptr = FindWindowEx(intptr, IntPtr.Zero, "ReBarWindow32", null);
intptr = FindWindowEx(intptr, IntPtr.Zero, "TabBandClass", null);
intptr = FindWindowEx(intptr, IntPtr.Zero, "DirectUIHWND", null);
return intptr;
}
private static IAccessible AccessibleObjectFromWindow(IntPtr hwnd)
{
Guid guid = new Guid("{2359BD84-0175-4783-8909-CBD181217D3C}"); // IAccessible
object obj = null;
uint id = 0U;
int num = AccessibleObjectFromWindow(hwnd, id, ref guid, ref obj);
var acc = (IAccessible)obj;
return acc;
}
private static object[] GetAccessibleChildren(IAccessible ao)
{
var childs = 0;
object[] ret = null;
int count = 0;
count = ao.accChildCount;
MessageBox.Show("Count value : " + count);
if (count > 0)
{
ret = new object[count];
AccessibleChildren(ao, 0, count, ret, out childs);
}
return ret;
}
private static IAccessible FindAccessibleDescendant(IAccessible parent, String strName)
{
int c = 0;
c = parent.accChildCount;
if (c == 0)
return null;
var children = AccChildren(parent);
foreach (var child in children)
{
if (child == null) continue;
if (strName.Equals(child.get_accName(0)))
return child;
var x = FindAccessibleDescendant(child, strName);
if (x != null) return x;
}
return null;
}
private static List<IAccessible> AccChildren(IAccessible accessible)
{
object[] res = GetAccessibleChildren(accessible);
var list = new List<IAccessible>();
if (res == null) return list;
foreach (object obj in res)
{
IAccessible acc = obj as IAccessible;
if (acc != null) list.Add(acc);
}
return list;
}
private static string UrlForTab(IAccessible tab)
{
try
{
var desc = tab.get_accDescription(0);
if (desc != null)
{
if (desc.Contains("\n"))
{
string url = desc.Substring(desc.IndexOf("\n")).Trim();
return url;
}
else
{
return desc;
}
}
}
catch { }
return "??";
}
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent,
IntPtr hwndChildAfter,
string lpszClass,
string lpszWindow);
[DllImport("oleacc.dll")]
internal static extern int AccessibleObjectFromWindow
(IntPtr hwnd, uint id, ref Guid iid,
[In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object ppvObject);
[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);
}
}
如有任何帮助,我们将不胜感激。
解决了这个问题。万一有人发现自己处于这种情况,这对我有帮助 http://www.codeproject.com/Articles/204929/Getting-current-browser-URL-with-VB-NET