使用 JScript 的 HTA 中的 ActiveX 事件处理程序
ActiveX event handlers in an HTA using JScript
在 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 中,即使使用静态事件处理和描述的语法 here:
var wdApp = new ActiveXObject('Word.Application');
wdApp.Visible = true;
function wdApp::Quit() {
window.alert('Quit');
};
失败:
0x800a138f - JScript runtime error: Object expected
此外,静态事件处理是 VBA/VB6 中的一个选项,因为声明可以标记为 Private
。但是,在 JScript 中,变量和处理程序都必须在全局范围内声明。
两个问题:
如何在 HTA 环境中使用 JScript 处理自动化创建对象的事件?
(注意:我知道在 WSH 中可以使用传递给 CreateObject
的前缀和名为 wdApp_Quit
的函数,但我正在寻找 HTA 解决方案。)
如何在不污染全局范围的情况下做到这一点?
有一个较旧的问题 here。
错误似乎是因为
在Javascript/JScriptfunction declarations are evaluated first,变量初始化之前。好像代码是这样写的:
var wdApp;
function wdApp::Quit() { ... }
wdApp = new ActiveXObject('Word.Application');
Microsoft JScript 解析器将 specially-named 声明(带有 ::
)解释为将函数附加为事件处理程序的指令。
但是在声明的时候,处理程序不能附加到wdApp
引用的对象上,因为wdApp
在那个时候仍然是undefined
.因此,错误。
解决办法是在wdApp
初始化后强制对函数声明求值。这可以通过以下三种方式之一完成1:
由于函数声明仅在函数范围内被提升,因此将函数声明包装在 IIFE 中:
var wdApp = new ActiveXObject('Word.Application');
(function() {
function wdApp::Quit() {
//do stuff here
}
})();
使用某种字符串 -> 代码机制创建声明 -- eval
、setTimeout
和字符串、window.execScript
或 new Function
:
var wdApp = new ActiveXObject('Word.Application');
eval('function wdApp::Quit() { ... }`);
初始化当前SCRIPT
块之前的变量。 Scripting Events 文章中的大多数示例通过在 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下还有第四种方式,但是涉及non-standardHTML而不是non-standardJavascript;但它只能在使用 HTML OBJECT
标记而不是 new ActiveXObject( ... )
声明对象时使用。
<script for="wdApp" event="Quit">
//do stuff here
</script>
在 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 中,即使使用静态事件处理和描述的语法 here:
var wdApp = new ActiveXObject('Word.Application');
wdApp.Visible = true;
function wdApp::Quit() {
window.alert('Quit');
};
失败:
0x800a138f - JScript runtime error: Object expected
此外,静态事件处理是 VBA/VB6 中的一个选项,因为声明可以标记为 Private
。但是,在 JScript 中,变量和处理程序都必须在全局范围内声明。
两个问题:
如何在 HTA 环境中使用 JScript 处理自动化创建对象的事件? (注意:我知道在 WSH 中可以使用传递给
CreateObject
的前缀和名为wdApp_Quit
的函数,但我正在寻找 HTA 解决方案。)如何在不污染全局范围的情况下做到这一点?
有一个较旧的问题 here。
错误似乎是因为
在Javascript/JScriptfunction declarations are evaluated first,变量初始化之前。好像代码是这样写的:
var wdApp; function wdApp::Quit() { ... } wdApp = new ActiveXObject('Word.Application');
Microsoft JScript 解析器将 specially-named 声明(带有
::
)解释为将函数附加为事件处理程序的指令。但是在声明的时候,处理程序不能附加到
wdApp
引用的对象上,因为wdApp
在那个时候仍然是undefined
.因此,错误。
解决办法是在wdApp
初始化后强制对函数声明求值。这可以通过以下三种方式之一完成1:
由于函数声明仅在函数范围内被提升,因此将函数声明包装在 IIFE 中:
var wdApp = new ActiveXObject('Word.Application'); (function() { function wdApp::Quit() { //do stuff here } })();
使用某种字符串 -> 代码机制创建声明 --
eval
、setTimeout
和字符串、window.execScript
或new Function
:var wdApp = new ActiveXObject('Word.Application'); eval('function wdApp::Quit() { ... }`);
初始化当前
SCRIPT
块之前的变量。 Scripting Events 文章中的大多数示例通过在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下还有第四种方式,但是涉及non-standardHTML而不是non-standardJavascript;但它只能在使用 HTML OBJECT
标记而不是 new ActiveXObject( ... )
声明对象时使用。
<script for="wdApp" event="Quit">
//do stuff here
</script>