.NET ユーザコントロールを Web に埋め込んで使っていたのですが、ユーザコントロールで発生したイベントを
クライアントサイドの javascript で記述したハンドラで受け取る必要がでてきたため、
ネットであちこち探してたどり着いたのが、この方法です。
通常の Active X コントロールでなら簡単にできることなのですが、.NET から COM の仕組みを利用するには、
少し追加作業が必要でした。なお、元ネタは Microsoft のサポート技術情報 313891 です。
以下では、Windows XP Professional SP2、Microsoft Visual Studio .NET 2003 (C#)、Internet Explorer 6.0 を使用しています。
まず .NET ユーザコントロールを作成します。
ただし、ここではまだ javascript でハンドリングできるイベントは記述せず、通常のユーザコントロールを作成します。
Visual Studio を起動し、メニューから [ファイル] - [新規作成] - [プロジェクト] を選択します。
[新しいプロジェクト] ダイアログが表示されるので、[プロジェクトの種類] に [Visual C# プロジェクト]、
[テンプレート] で [Windows コントロール ライブラリ] を選択します。
[プロジェクト名] は適当に入力してください。ここでは TestCtrlLib としました。
入力が済んだら [OK] をクリックしてください。
デフォルトのユーザコントロールとして UserControl1 が挿入されたプロジェクトが作成されます。
ユーザコントロールの名前は適当に変更してください。ここでは、TestCtrl にしています。 なお、Visual Studio 2003 では、ユーザコントロールのファイル名を変更しても、 対応するクラス名などは変更してくれませんので、コードを表示し、クラスの名前とコンストラクタの名前も TestCtrl に変更してください。
次にコントロール上にボタンを載せ、ボタンの名称を cmdGO にした後、ボタンをダブルクリックし、 イベントハンドラを以下のように記述します。
これでとりあえずコントロールはできあがりです (って押されたら「ハロー」っていうメッセージボックス出すだけですが…)。
メニューから [ビルド] - [ソリューションのビルド] を選択して、ビルドしてください。
ここでは Debug ビルドのままですので、ユーザコントロールを格納したファイルは、
[プロジェクトのディレクトリ\bin\Debug\TestCtrlLib.dll] になります。
次に、ユーザコントロールを埋め込む先の Web アプリケーションを作成します。
なお、ローカルの IIS を使用しますので、起動しているのを確認しておいてください。
Visual Studio を起動し、メニューから [ファイル] - [新規作成] - [プロジェクト] を選択します。
[新しいプロジェクト] ダイアログが表示されるので、[プロジェクトの種類] に [Visual C# プロジェクト]、
[テンプレート] で [ASP.NET Web アプリケーション] を選択します。
[プロジェクト名] は適当で構いません。ここでは http://localhost/WebTestCtrlApp としました。
[OK] をクリックすると、プロジェクトが新規作成されます。
ローカルの IIS をデフォルトのまま使用している場合、
C:\Inetpub\wwwroot\WebTestCtrlApp ディレクトリが作成され、プロジェクトのファイル群が配置されます。
ここにさきほど作成したユーザコントロールのファイルをコピーします。
※コピーする際にはアクセス権に注意してください。ASP.NET から参照できるよう権限を設定してください。
次に、デフォルトで作成される WebForm1.aspx にユーザコントロールを埋め込みます。
デザイナで [HTML] を選択し HTML を表示し、<object> タグを使ってユーザコントロールを埋め込みます。
id はこのページでのユーザコントロールの id になります。classid にはユーザコントロールのファイル名と
ユーザコントロールのクラス名をネームスペースを含めて # で区切って記述します。
これで埋め込み先のページは完成です。ビルドして、実行してください。
埋め込まれたユーザコントロールがページ上に表示され、「ゴー」ボタンを押すと、「ハロー」のメッセージボックスが表示されれば OK です。
ユーザコントロールにイベントを実装します。
.NET の枠組みの中で IE へのイベント発行ができるかどうかは不明です (色々あさってみたのですが、
資料に行き当たりませんでした…)。ここでは、ユーザコントロールに COM のシンクイベントを実装することで
イベント通知を実現しています。
先に作成した、TestCtrlLib プロジェクトを開きます。
以下に追加するコードが利用するので、using System.Runtime.InteropServices を追加します。
イベントのシグネチャ定義としてのデリゲートを定義します。 ここでは、表示したいメッセージを引数とする HelloEventHandler を定義しました。
シンクイベントインタフェースを定義します。
なお、GuidAttribute の GUID は GUIDGEN.exe などを使って適宜作成してください。
DispIdAttribute はイベントの番号になりますので、これも適当に付番してください。
なお、ここで定義するイベントインタフェースのシグネチャは先のデリゲートのシグネチャと合致している必要があります。
クラスに属性情報を追加します。
属性情報で、イベントのインタフェースを指定し、また、このクラスからのインタフェースを
自動的にディスパッチインタフェースとして扱うよう指定しています (ここでのクラスのインタフェースとは、
このクラスで public 指定されたメンバ変数やメソッドのことです)。
イベントインタフェースを実装するため、HelloEvent を格納する変数を定義します。
最後に「ゴー」ボタンが押された際にイベントを発生させるようにします。
以上でユーザコントロール側は完了です。リビルドして、Web アプリケーション下にコピーしてください。
ユーザコントロールで発生させたイベントをハンドリングするために Web ページ側に javascript でハンドラを記述します。
先に作成した WebTestCtrlApp を開き、WebForm1.apsx を HTML の編集画面にし、以下のコードを記述します。
※わざわざ TestCtrl_HelloEvent() を定義して呼び出す必要はなく、イベントハンドラから直接 alert(msg) としても良いです。
Web ページ側はこれで完成です。あとは実行すれば良いだけですが、実行するためには .NET のセキュリティ設定を
変更しておく必要があります。そのままだとたぶん動作しません。
とりあえず私の環境では、http://localhost/ を信頼済みサイトに登録し、.NET のセキュリティで信頼済みサイトを
FullTrust に設定しています。
信頼済みサイトの設定は IE のメニューから [ツール] - [インターネット オプション] を選び、
表示される [インターネット オプション] ダイアログで、[セキュリティ] タブを選択し、[信頼済みサイト] をクリックしてから、
[サイト] ボタンをクリックし、[信頼済みサイト] ダイアログを表示します。
[次の Web サイトをゾーンに追加する] の箇所のテキストボックスに http://localhost/ と入力し [追加] ボタンをクリックすると、
入力した URL が [Web サイト] 欄に移動して追加されます。なお、[このゾーンのサイトにはすべてサーバの確認 (https:) を必要とする]
チェックボックスは外しておいてください。
追加したら、[OK] をクリックしてダイアログを閉じてください。
.NET セキュリティの設定は .NET Configuration 1.1 を起動し、ツリーから [マイ コンピュータ] - [ランタイム セキュリティ ポリシー]
- [コンピュータ] - [コードグループ] から信頼済みサイトのポリシーを選択します。
※私の環境では名称に対応するリソースがうまく読み込めず、コードグループ以下のツリーのノードの名称がおかしくなっています。実働上問題ないので放ってありますが、見にくくてすみません。
[コードグループ プロパティの編集] をクリックし、編集ダイアログが開いたら、[アクセス許可セット] タブで、
[アクセス許可セット] に [FullTrust] を選択し、[OK] をクリックします。
また、イベント通知を COM の仕組みを使って行う関係上、IE の Active X コントロールのセキュリティも設定しておく必要があるようです。
[ツール] - [インターネット オプション] を選び、表示される [インターネット オプション] ダイアログで、
[セキュリティ] タブを選択し、[信頼済みサイト] をクリックしてから、[レベルのカスタマイズ] をクリックし、
[セキュリティの設定] ダイアログを表示します。ActiveX コントロールとプラグインの設定を変更します。
私の環境では、
ActiveX コントロールとプラグインの実行 | 有効にする |
ActiveX コントロールに対して自動的にダイアログを表示 | 有効にする |
スクリプトを実行しても安全だとマークされていない ActiveX コントロールの初期化とスクリプトの実行 | ダイアログを表示する |
スクリプトを実行しても安全だとマークされている ActiveX コントロールのスクリプトの実行 | 有効にする |
バイナリ ビヘイビアとスクリプト ビヘイビア | 有効にする |
署名済み ActiveX コントロールのダウンロード | 有効にする |
未署名の ActiveX コントロールのダウンロード | ダイアログを表示する |
のように設定しています (というかデフォルトのまま)。
以上の設定を確認した後、実行してみてください。イベントがでハンドリングされ、以下のように「ハロー」が表示されれば OK です。
おまけ的ですが、ユーザコントロールのボタンクリック時にスレッドを起動し、
スレッド側からイベント通知させてみます。
TestCtrlLib を開き、以下のように修正/追加します。
リビルドして、Web アプリケーション下にコピーしてから実行してみてください。3 秒の遅延のあと、
「ハロー」と表示されるはずです。
VC などで ActiveX コントロールを作成し、スレッド側からイベント通知しようとした場合、
マーシャリングの処理などを自前でする必要があり、少々ややこしいのですが、
.NET では Invoke() がすべてやってくれるようです。このあたりは .NET の便利さを感じます。
※なお、このサンプルではスレッド実行中に IE を閉じた場合への対処をしていませんのでご注意ください。