使用JScript的HTA中的ActiveX事件处理程序



在C#中,我可以编写如下事件处理程序:

var wdApp = new Microsoft.Office.Interop.Word.Application();
wdApp.DocumentBeforeSave += (Document doc, ref bool saveAsUI, ref bool cancel) => {
//do stuff here
};

在VBA/VB6中,我可以使用静态事件处理:

Dim WithEvents wdApp As Word.Application
Private Sub wdApp_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean)
'do stuff here
End Sub

我更喜欢使用动态事件处理。然而,在JScript中,即使使用以下语法的静态事件处理:

var wdApp = new ActiveXObject('Word.Application');
wdApp.Visible = true;
function wdApp::Quit() {
window.alert('Quit');
};

它失败了:

0x800a138f-JScript运行时错误:需要对象

此外,静态事件处理是VBA/VB6中的一个选项,因为声明可以标记为Private。但是,在JScript中,变量和处理程序都必须在全局作用域中声明。

两个问题:

  1. 如何在HTA环境中使用JScript处理Automation创建的对象的事件(注意:我知道在WSH中使用传递给CreateObject的前缀和名为wdApp_Quit的函数是可能的,但我正在寻找HTA解决方案。)

  2. 如何在不污染全球范围的情况下做到这一点


这里有一个老问题。

错误似乎是因为

  1. 在Javascript/JScript中,在初始化变量之前,首先对函数声明进行求值。就好像代码是这样写的:

    var wdApp;
    function wdApp::Quit() { ... }
    wdApp = new ActiveXObject('Word.Application');
    
  2. Microsoft JScript解析器将特殊命名的声明(使用::)解释为将函数附加为事件处理程序的指令。

  3. 但在声明时,处理程序不能附加到wdApp引用的对象,因为此时的wdApp仍然是undefined。因此,出现了错误。

解决方案是在初始化wdApp之后强制计算函数声明。这可以通过1的三种方式之一实现:

  1. 由于函数声明仅被提升到函数范围内,因此将函数声明包装在IIFE:中

    var wdApp = new ActiveXObject('Word.Application');
    (function() {
    function wdApp::Quit() {
    //do stuff here
    }
    })();
    
  2. 使用某种字符串创建声明->代码机制——eval、带字符串的setTimeoutwindow.execScriptnew Function:

    var wdApp = new ActiveXObject('Word.Application');
    eval('function wdApp::Quit() { ... }`);
    
  3. 初始化当前SCRIPT块之前的变量。ScriptingEvents文章中的大多数示例都是通过在SCRIPT块之前的某个元素上设置id属性来实现这一点的:

<object progid="ordersystem.clsorder" id="myorder" events="true"/>
<script language="jscript">
function myorder::onNew() {
WScript.Echo("new order received from myorder")
}
//...

,但这也可以使用多个SCRIPT块来完成:

<SCRIPT>
var wdApp = new ActiveXObject('Word.Application');
</SCRIPT>
<SCRIPT>
function wdApp::Quit() {
//do stuff here
}
</SCRIPT>

就污染全局命名空间而言,只有第三个变体要求wdApp在全局命名空间中;其他两种变体可以封装在IIFE中。


1.从技术上讲,IE和HTAs下有第四种方式,但它涉及非标准HTML,而不是非标准Javascript;但是,只有使用HTMLOBJECT标记而不是new ActiveXObject( ... )声明对象时,才能使用它

<script for="wdApp" event="Quit">
//do stuff here
</script>

最新更新