Firefox addon Firefox引导扩展:获取浏览器窗口的本机HWND句柄

Firefox addon Firefox引导扩展:获取浏览器窗口的本机HWND句柄,firefox-addon,xul,xpcom,jsctypes,Firefox Addon,Xul,Xpcom,Jsctypes,我有一个外部应用程序,我希望它在浏览器窗口顶部显示一些信息。我的引导扩展需要将浏览器窗口句柄(本机HWND)以及其他一些有关窗口的有用信息传递给我的应用程序。我能够完成它们之间的通信,唯一缺少的是获取Firefox窗口的本地HWND的方法 我读了很多关于它的书,虽然我相信这是可能的,但我找不到一个有效的解决方案。以下是我迄今为止所尝试的: 这个应该给我nsIBaseWindow,这样我就可以得到nsIBaseWindow.nativeHandle或nsIBaseWindow.ParentNati

我有一个外部应用程序,我希望它在浏览器窗口顶部显示一些信息。我的引导扩展需要将浏览器窗口句柄(本机HWND)以及其他一些有关窗口的有用信息传递给我的应用程序。我能够完成它们之间的通信,唯一缺少的是获取Firefox窗口的本地HWND的方法

我读了很多关于它的书,虽然我相信这是可能的,但我找不到一个有效的解决方案。以下是我迄今为止所尝试的:

这个应该给我
nsIBaseWindow
,这样我就可以得到
nsIBaseWindow.nativeHandle
nsIBaseWindow.ParentNativeWindow
,但没有成功:

var window = SomeDOMWindow; // Informative
var baseWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                        .getInterface(Components.interfaces.nsIWebNavigation)
                        .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
                        .treeOwner
                        .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                        .getInterface(Components.interfaces.nsIXULWindow)
                        .docShell
                        .QueryInterface(Components.interfaces.nsIBaseWindow);
上面的代码在论坛上广泛传播,但我无法让它为我工作

另一个似乎不太准确,因为它根据窗口的类和标题获取HWND,这可能导致错误的结果:

Components.utils.import("resource://gre/modules/ctypes.jsm");
var lib = ctypes.open("user32.dll");
var fww = lib.declare("FindWindowW", ctypes.winapi_abi,
  ctypes.voidptr_t, ctypes.jschar.ptr, ctypes.jschar.ptr);
var sfw = lib.declare("SetForegroundWindow", ctypes.winapi_abi,
  ctypes.int32_t, ctypes.voidptr_t);
var hwnd = fww("MozillaWindowClass", document.title);
setTimeout(function() {
  sfw(hwnd);
  lib.close();
}, 3000);

任何帮助都将不胜感激。

窗口必须是根窗口(即
ChromeWindow
的实例)

下面的代码应该可以工作

var win=Cc[“@mozilla.org/appshell/window mediator;1”].getService(Ci.nsIWindowMediator.getMostRecentWindow(“导航器:浏览器”);
var basewindow=win.QueryInterface(Ci.nsInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
树主先生
.QueryInterface(Ci.NSInterfaceRequestor)
.nsIBaseWindow;
var nativehandle=basewindow.nativehandle;

问题是我在注册的
xul窗口中从
主题
参数查询错误的界面。我需要得到一个
nsIDOMWindow
而不是
nsIXULWindow
,这样我问题中提到的第一个代码就可以工作了。因此,现在我正在使用@Noit建议的一些代码执行以下操作:

observe: function(subject, topic, data) {
    var newWindow  = subject.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
    var basewindow = newWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .treeOwner
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .nsIBaseWindow;
    var nativehandle = basewindow.nativeHandle;
}
而且它有效


非常感谢您的帮助。

我也遇到了这个问题,可能会很好:

Cu.import("resource://gre/modules/ctypes.jsm");

/*start getcursorpos*/
var lib = ctypes.open("user32.dll");

/*foreground window stuff*/
var FindWindowA = lib.declare('FindWindowA', ctypes.winapi_abi, ctypes.uint32_t, ctypes.jschar.ptr, ctypes.jschar.ptr)
var GetForegroundWindow = lib.declare('GetForegroundWindow', ctypes.winapi_abi, ctypes.uint32_t)
function doFindWindow() {
    var wm = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
    var title = wm.getMostRecentWindow('navigator:browser').gBrowser.contentDocument.title;
    Cu.reportError('title=' + title)
    var ret = FindWindowA('', title + ' - Mozilla Firefox');
    //var ret = GetForegroundWindow();

    Cu.reportError(ret);
}
/*end foreground window stuff*/
用户“paa”中的代码在Firefox版本69之前一直有效。 如果在Firefox 70中执行,您将得到一个异常:

TypeError: win.QueryInterface is not a function
这很奇怪,因为变量
win
在Firefox 69和70中具有相同的内容

当我执行
alert(win)
时,我在两种浏览器中都得到:
“[object ChromeWindow]”

alert(win.document.title)
在两种浏览器中正确显示文档的标题

我下载了两个Firefox版本的源代码来比较它们,并可能找到原因。但是Firefox的源代码非常庞大(2GB),几乎完全没有评论。我发现我用这种方法是在浪费时间

要理解Firefox的源代码是非常困难的,Firefox运行在多个相互通信的进程上。变量<代码> Win >对应于C++类<代码> MZIDOMWOWOVER代理> /COD>或<代码> NSHCROMEOUTWORKOVEXORGODS。但这些似乎只是其他类的包装类。最后,我放弃了理解Firefox源代码的尝试

但经过几个小时的反复尝试,我终于找到了解决办法

更简单的是:

var baseWindow = win.docShell
                    .treeOwner
                    .nsIBaseWindow; 

它可以在Firefox70到79(目前是最新版本)上运行。但是,这段新代码不在Firefox版本上运行,我需要从
xul窗口内注册
ChromeWindow
事件观察程序,以便测试您的解决方案。我有事件处理程序:
observe:function(subject,topic,data){…}
,这是我需要获取句柄的地方,但我只知道如何从那里获取
nsIDOMWindow
,而不是创建的
ChromeWindow
,注册的
xul窗口
通知的主题是您正在查找的窗口。我试图使用它,但它是一个
nsi支持的
界面。当我试图从中获取
basewindow
时,我得到一个错误:
[nsinterfacerequestor.getInterface]“nsresult:”0x80004002(NS_NOINTERFACE)“
要进行测试,您可以将其代码复制粘贴到草稿行中,并将环境设置为“浏览器”。效果很好。@Kekas我想当观察者收到
xulwindowregistered
主题通知时,窗口对象的初始化没有完成。也许你应该等到
load
事件被触发。非常感谢你分享这段代码,它将帮助人们再次感谢你分享这段代码,我遇到了一个问题,当时我正在设置一个窗口的标题,然后做
FindWindow
,但是FindWindow没有找到它,因为它在更改窗口标题后运行得太快了。然后我想起了这个主题,现在甚至不需要
FindWindow
超级男人再次感谢!!这就是人们应该始终共享解决方案的原因!:)这段代码在Firefox70上不再有效。请看我的答案。它不是很可靠,因为它使用窗口的标题,并且一些发行版有不同的名称。更不用说标题可能会在过程中更改,或者多个窗口具有相同的标题,最终可能会得到错误的句柄。
TypeError: win.docShell is undefined