JavaScriptでActiveXイベントを処理する方法
-
02-07-2019 - |
質問
これは、回答こちらのフォローアップです。
イベントを発生させているカスタムActiveXコントロール(<!> quot; ReceiveMessage <!> quot; <!> quot; msg <!> quot;パラメーター)がJavascriptで処理される必要があるウェブブラウザ。これまで、次のIE専用の構文を使用して、さまざまなプロジェクトでこれを実現できました。
function MyControl::ReceiveMessage(msg)
{
alert(msg);
}
ただし、コントロールが埋め込まれているレイアウト内では、Javascriptはコントロールを見つけることができません。具体的には、これをプレーンなHTMLページに入れると正常に動作しますが、<Form>
タグでラップされたASPXページに入れると、<!> quot; MyControl is undefined <!> quot;エラー。次のバリエーションを試しました:
var GetControl = document.getElementById("MyControl");
function GetControl::ReceiveMessage(msg)
{
alert(msg);
}
...ただし、Javascriptエラーが発生します<!> quot; GetControl is undefined。<!> quot;
ActiveXコントロールから送信されるイベントを処理する適切な方法は何ですか?今のところ、IEでこれを機能させることにのみ興味があります。これは、私たちがしていることのためのカスタムActiveXコントロールでなければなりません。
ありがとう。
解決
次のスクリプトブロック形式を使用してこれを機能させることができましたが、これが最善の方法であるかどうかはまだ興味があります。
<script for="MyControl" event="ReceiveMessage(msg)">
alert(msg);
</script>
他のヒント
以前にアプリケーションでactivexを使用したことがあります。オブジェクトタグをASP.NETフォームに配置すると、次のJavaScriptが機能します。
function onEventHandler(arg1, arg2){
// do something
}
window.onload = function(){
var yourActiveXObject = document.getElementById('YourObjectTagID');
if(typeof(yourActiveXObject) === 'undefined' || yourActiveXObject === null){
alert('Unable to load ActiveX');
return;
}
// attach events
var status = yourActiveXObject.attachEvent('EventName', onEventHandler);
}
OK、ただし、継承されたUserControl(ActiveX)でC#(.NET 2.0)を使用している場合... 動作させる唯一の方法は、<!> quot; Extending <!> quot;イベントのハンドラー機能: http://www.codeproject.com/KB/dotnet/extend_events。 aspx?display = Print
友人のWerner Willemsens氏からの上記のプロジェクトリンクが私のプロジェクトを救ってくれました。 そうしないと、javascriptはイベントハンドラーにバインドできません。
彼は<!> quot; extension <!> quot;を使用しました。彼が選択した例のために複雑な方法で、しかしあなたがそれを単純にするならば、イベント自体に直接ハンドルをアタッチすると、それも機能します。 C#ActiveXは<!> quot; ScriptCallbackObject <!> quot;をサポートする必要があります。以下のようなjavascript関数にイベントをバインドするには:
var clock = new ActiveXObject("Clocks.clock");
var extendedClockEvents = clock.ExtendedClockEvents();
// Here you assign (subscribe to) your callback method!
extendedClockEvents.ScriptCallbackObject = clock_Callback;
...
function clock_Callback(time)
{
document.getElementById("text_tag").innerHTML = time;
}
もちろん、IObjectSafetyおよびその他のセキュリティ関連のものを実装して、より良く機能させる必要があります。
「MyControl」というIDを持つActiveX要素がページにある場合、javascriptハンドラの構文は次のとおりです。
function MyControl::ReceiveMessage(msg)
{
alert(msg);
}
このコードはformタグ内で機能することがわかりました。この例では、コールバックはJavaScriptからActiveXコントロールに渡される関数パラメーターであり、callbackparamはactiveXコントロール内で生成されるコールバックイベントのパラメーターです。このようにして、さまざまな種類のイベントに同じイベントハンドラーを使用します。個別のイベントハンドラーの束を宣言するのではなく、
<object id="ActivexObject" name="ActivexObject" classid="clsid:15C5A3F3-F8F7-4d5e-B87E-5084CC98A25A"></object>
<script>
function document.ActivexObject::OnCallback(callback, callbackparam){
callback(callbackparam);
}
</script>
私の場合、ActiveXコントロールを動的に作成し、それらのイベントをリッスンする方法が必要でした。次のようなものを動作させることができました:
//create the ActiveX
var ax = $("<object></object>", {
classid: "clsid:" + clsid,
codebase: install ? cabfile : undefined,
width: 0,
height: 0,
id: '__ax_'+idIncrement++
})
.appendTo('#someHost');
そして、イベントのハンドラーを登録するには:
//this function registers an event listener for an ActiveX object (obviously for IE only)
//the this argument for the handler is the ActiveX object.
function registerAXEvent(control, name, handler) {
control = jQuery(control);
//can't use closures through the string due to the parameter renaming done by the JavaScript compressor
//can't use jQuery.data() on ActiveX objects because it uses expando properties
var id = control[0].id;
var axe = registerAXEvent.axevents = registerAXEvent.axevents || {};
axe[id] = axe[id] || {};
axe[id][name] = handler;
var script =
"(function(){"+
"var f=registerAXEvent.axevents['" + id + "']['" + name + "'],e=jQuery('#" + id + "');"+
"function document." + id + "::" + name + "(){"+
"f.apply(e,arguments);"+
"}"+
"})();";
eval(script);
}
このコードを使用すると、クロージャーを使用して、eval()のスコープを最小化できます。
ActiveXコントロールの<object>
要素は既にドキュメントに追加されている必要があります。そうしないと、IEは要素を見つけられず、スクリプトエラーが発生します。
ActiveXコントロールが別の名前または別のスコープで公開されているため、MyControl :: ReceiveMessageの例は機能しないと思います。
GetControl :: ReceiveMessageの例では、GetControl参照が設定される前に関数定義が解析されているため、有効なオブジェクトを参照せず、関数をオブジェクトにバインドできません。
MSスクリプトデバッガーを使用して、コントロールの既定の参照が別の名前または別のスコープ(おそらくフォームの子として)に存在するかどうかを判断することにより、この問題を攻撃します。コントロールの正しい参照を特定できる場合、MSDNの記事で指定されているAutomagic ::メソッドを使用して関数を適切にバインドできるはずです。
もう1つの考えとして、参照はIDではなくオブジェクトの名前に基づいている可能性があるため、両方を設定してみてください:)