これは回答へのフォローアップです ここ 。
WebブラウザーのJavaScriptで処理する必要があるイベント(「msg」パラメーターを指定した「ReceiveMessage」)を発生させるカスタムActiveXコントロールがあります。これまで、さまざまなプロジェクトで次のIEのみの構文を使用してこれを実現することができました。
function MyControl::ReceiveMessage(msg)
{
alert(msg);
}
ただし、コントロールが埋め込まれているレイアウト内では、Javascriptはコントロールを見つけることができません。具体的には、これをプレーンHTMLページに配置すると正常に機能しますが、<Form>
タグでラップされたASPXページに配置すると、「MyControl is undefined」エラーが発生します。以下のバリエーションを試しました。
var GetControl = document.getElementById("MyControl");
function GetControl::ReceiveMessage(msg)
{
alert(msg);
}
...しかし、Javascriptエラー「GetControl is undefined」が発生します。
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)を使用している場合...これを機能させる唯一の方法は、イベントのハンドラー機能を「拡張」することです http://www.codeproject .com/KB/dotnet/extend_events.aspx?display = Print
友人のウェルナーウィレムセンス氏からの上記のプロジェクトリンクが私のプロジェクトを保存しました。そうしないと、JavaScriptがイベントハンドラーにバインドできません。
彼が選択した例のため、彼は「拡張」を複雑な方法で使用しましたが、単純にすると、ハンドルをイベント自体に直接アタッチすることもできます。 C#ActiveXは、 "ScriptCallbackObject"をサポートして、イベントを以下のような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やその他のセキュリティ機能を実装して、より適切に機能させる必要があります。
このコードはformタグ内で機能することがわかりました。この例では、コールバックはJavaScriptによってActiveXコントロールに渡される関数パラメーターであり、コールバックパラメーターは、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は要素を見つけられず、スクリプトエラーが発生するだけです。
「MyControl」のIDを持つページにActiveX要素がある場合、JavaScriptハンドラーの構文は次のようになります。
function MyControl::ReceiveMessage(msg)
{
alert(msg);
}
MyControl :: ReceiveMessageの例は、ActiveXコントロールが別の名前または別のスコープで公開されているため機能しないと思います。
GetControl :: ReceiveMessageの例では、GetControl参照が設定される前に関数定義が解析されているため、有効なオブジェクトを参照しておらず、関数をオブジェクトにバインドできないと思います。
この問題を攻撃するには、MSスクリプトデバッガーを使用して、コントロールの既定の参照が別の名前または別のスコープ(フォームの子として)に存在するかどうかを確認します。コントロールの正しい参照を決定できれば、MSDNの記事で指定されているAutomagic ::メソッドを使用して関数を適切にバインドできるはずです。
もう1つ考えてみてください。参照はIDではなくオブジェクトの名前に基づいている可能性があるため、両方を設定してみてください:)