Insider's Eye

“WPF/E”開発を体験してみよう!

デジタルアドバンテージ 一色 政彦
2006/12/21


“WPF/E”コントロールのロード処理

 次のHTMLコードは、最も単純な「“WPF/E”コントロールをホストするWebページ」である。

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <!-- “WPF/E”コントロールを生成するJavaScriptコード -->
  <script type="text/javascript" src="agHost.js"></script>
</head>
<body style="background:yellow;">
  <div>
    下に400×400の“WPF/E”コントロール(ID:wpfeControl1)が存在します。
  </div>

  <div id="wpfeControl1Host">
    <script type="text/javascript">
    <!--
      // “WPF/E”コントロールの作成
      new agHost(
        "wpfeControl1Host", // ホスト要素ID
        "wpfeControl1",     // “WPF/E”コントロールID
        "400",              // コントロールの幅
        "400",              // コントロールの高さ
        "white",            // コントロールの背景色
        null,               // ソース要素名
        "plugin.xaml",      // 外部のXAMLファイル名
        "false",            // ウィンドウレスかどうか
        "30",               // 最大フレームレート
        null                // エラー・ハンドラ名
      );
    // -->
    </script>
  </div>

</body>
</html>
“WPF/E”コントロールをホストする最も単純なHTMLコード
実はこのコードはVisual Studio 2005の“WPF/E”用プロジェクト・テンプレートで生成される「ひな形のコード」とほぼ同じだ。補足説明が必要と思われるものだけ、以下に説明を追加する。
  “WPF/E”コントロールをホストするHTML要素である<div>タグのID名を指定する。このコードでは、すぐ上にある「<div id="wpfeControl1Host">」というコードと同じID名の「wpfeControl1Host」を指定している。
  作成する“WPF/E”コントロールのIDを指定する。このIDは、JavaScriptコードで“WPF/E”コントロールのDOM形式(詳細後述)のオブジェクトを取得する際に使用する(具体的には「var wpfeControl = document.getElementById("WpfeControl1");」というコード)。
  ロード時に実行される「インラインXAMLスクリプト」のタグ名を指定する。デフォルト動作に任せる場合は「null」を指定する。これに関して詳しくは、前編の「HTMLファイル内にインラインで記述した『XAMLスクリプト・コード+JavaScriptコード』」における「SourceElement属性」の説明を参照してほしい。
  ウィンドウレスかどうかを指定する。ウィンドウレスをtrueに指定した場合、BackgroundColorプロパティに指定されたアルファ値によって、HTMLページの背景色とブレンドされる。その際、BackgroundColorプロパティには「#AARRGGBB」という16進表記のスタイルで指定する(RGBは赤緑青を表し、Aはアルファ値を表す)。
  最大フレームレートを指定する(デフォルトは「30」)。“WPF/E”コンテンツをレンダリングする際の実際のフレームレートは、システムのロード・パフォーマンスに依存する。限界の最大フレームレートは「64」であるため、それ以上の数値を指定しても「64」と見なされる。
  エラー発生時に実行したい「インラインJavaScript」のタグ名を指定する。デフォルト動作に任せる場合は「null」を指定する。

 このコードでは、まず「agHost」というオブジェクトを生成しているが(各パラメータの意味については、上記コードのコメントと下部の説明を参照されたい)、このagHostオブジェクトこそが“WPF/E”コントロールである。

 agHostオブジェクトを生成するコンストラクタ関数は、JavaScriptファイル(agHost.js)で定義されている(このファイルはHTMLコードの<head>部分にある「<script type="text/javascript" src="agHost.js"></script>」というコードによりロードされている)。

 このJavaScriptコードの内部では、ActiveXコントロール用の<OBJECT>タグや、プラグイン用の<EMBED>タグがHTMLコードとして動的に呼び出され、agHostオブジェクトがWebブラウザのActiveXコントロールもしくはプラグインとして生成される仕組みになっている。

 上記のコードので指定されるXAMLファイル(この場合にはplugin.xaml)では、Canvasオブジェクトを使ってキャンバスとなるエリアを宣言しながら、UIをツリー階層的に構築している(XAMLコードで宣言される各オブジェクトは、ルートのCanvasオブジェクトから順に階層的なツリー構造の親子関係を持つことになる。なお、XAMLファイルの中に記述可能なオブジェクトに関しては、「“WPF/E”のオブジェクトのリファレンス」を参照してほしい)。

 以上、すべて(HTML&JavaScript&XAML)のコードを次の.ZIPファイルにまとめた。

DOMによる“WPF/E”コンテンツへのアクセスと制御

 “WPF/E”は、W3C標準(Web標準テクノロジ)が定義する「HTML DOM(Document Object Model)」、および「“WPF/E”Object Model」(=“WPF/E”特有のオブジェクト・モデル。以降、WOM)というプログラミング・インターフェイスにのっとって、その機能を外部からアクセス、制御できるようにしている。

 具体的には、IE(Internet Explorer)が持つ「DHTML Document Object Model」、もしくはFirefoxなどのMozillaベースのブラウザが持つ「Gecko DOM」などのHTML DOMの機能(つまりドキュメントの構造表現とそれへのアクセス機能)を活用して、WOMのドキュメント・オブジェクト(つまりXAMLコードで宣言された、階層的なツリー構造を持つ内容。以降、WOMオブジェクト)にアクセスできるようにしている。

 これにより、“WPF/E”コンテンツのJavaScriptコードやマネージ・コードは、(“WPF/E”コントロール上にロードされた)XAMLコードに簡単にアクセスしてさまざまな処理を実行できるというわけだ。例えば、WOMオブジェクトにアクセスしてそれが持つメソッドを利用することで、「JavaScriptコードでXAMLコード上に動的にUIオブジェクトを追加したり」「JavaScriptコードでXAMLコード上にあるビデオの再生を制御したり」することが可能である。

 なお先ほどの「“WPF/E”ランタイムの仕組み」の説明では、JavaScriptコードから(HTML DOMの機能を経由して)WOMオブジェクトにアクセス、制御する方法を「JavaScript DOM API」、マネージ・コードからWOMオブジェクトにアクセス、制御する方法を「.NET DOM API」と表現した。

 参考までに、JavaScript DOM APIで利用可能な、WOMが持つ代表的なメソッドを示しておこう。

メソッド 説明
CreateFromXAML 【“WPF/E”コントロールのみ】
XAMLコンテンツを動的に作成する。既存の“WPF/E”コンテンツのオブジェクト階層に新たなオブジェクトを付け加えるようなこともできる。その際、TextBlockのような単体のオブジェクトだけでなく、複数のオブジェクトを含むツリー全体を追加することも可能だ
FindName 【“WPF/E”コントロール/UIオブジェクト】
“WPF/E”コンテンツのオブジェクト階層内にあるオブジェクトを検索する。この際、検索される名前は、XAMLコードとして記述した、(オブジェクトに対する)「x:Name」属性の値である(「Name」の前にある「x:」は、「xmlns:x」属性で指定した名前空間。要するに、「x:Name」は「http://schemas.microsoft.com/winfx/2006/xaml」名前空間のName属性を意味する)
Reload 【“WPF/E”コントロールのみ】
“WPF/E”コントロールをリロードする。“WPF/E”コントロールが持つプロパティを強制的に変更したい場合に使用する
Play 【MediaElementオブジェクトのみ】
メディア(ビデオなど)を再生する
Stop 【MediaElementオブジェクト/Storyboardオブジェクト】
メディアやアニメーションを停止する
JavaScript DOM APIで使用できるWOMの代表的なメソッド
Storyboardオブジェクトはアニメーションを扱うもので、MediaElementオブジェクトはビデオを扱うものだ。ほかにも使えるメソッドはあるので、詳しくは“WPF/E”のメソッドのリファレンスを見てほしい(現在、ページが表示されないものもある)。

 このメソッドを活用したコード例も示しておこう。例えば、FindNameメソッドで見つけたオブジェクトのTextプロパティをカスタマイズするには、次のようなJavaScriptのコードを書けばよい。

function setCaption(captionString) {
  var control = document.getElementById("WpfeControl1");
  control.findName("myTextBlock").Text = captionString;
}
JavaScript DOM APIを活用したコード例
このsetCaption関数では、“WPF/E”コントロールのDOMオブジェクトを取得し、さらにFindNameメソッドにより「myTextBlock」という名前のTextBlockオブジェクト(WOMオブジェクト)を取得して、さらにそのTextプロパティに、関数のパラメータで渡された値(captionString変数)を指定している。

“WPF/E”コンテンツのイベント処理

 “WPF/E”では、コンテンツ内のオブジェクトがクリックされるタイミングなどで、イベントを発生させることができる。例えば、“WPF/E”コンテンツが“WPF/E”コントロールにロードされたときにLoadedイベントを発生させるには、次のようなXAMLコードを記述すればよい。

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Loaded="javascript:root_Loaded">
  ……中略……
</Canvas>
Loadedイベントを発生させるXAMLコードの例
トップ・レベル(=ルート)のCanvasオブジェクトにLoaded属性を記述することで、Loadedイベントを発生させることができる。Loaded属性の値には、イベント・ハンドラ名を記述する。この例では「javascript:root_Loaded」と書かれているが、これはJavaScriptコードの「root_Loaded関数」をLoadedイベント・ハンドラとして用いることを宣言している。

 Loadedイベントに対するJavaScriptによるイベント・ハンドラのコードは、次のようになる。

function root_Loaded(sender, args) {

  // 「button」という名前のオブジェクトを見つける
  var button = sender.findName("button");

  // buttonオブジェクトのmouseLeftButtonUpイベント・ハンドラとして
  // JavaScriptコードのhandleMouseUp関数を設定する
  button.mouseLeftButtonUp = "javascript:handleMouseUp";
}
Loadedイベント・ハンドラのJavaScriptコードの例
buttonオブジェクトは、XAMLコードで「<Canvas x:Name="button">」と定義されている。つまりbuttonオブジェクトは、「button」という名前のCanvasオブジェクトである。

 このコードを見ると分かるように、“WPF/E”のイベント・ハンドラ関数は、次の2つのパラメータを要求する。

  • 第1パラメータ(sender):イベント発生元のオブジェクト。上記の例では、ルートのCanvasオブジェクトになる(このオブジェクトのLoaded属性を指定したため)。ToStringメソッドを呼び出せば、オブジェクトの型を取得することができる(例えば「alert(sender.ToString());」というコードを記述すれば、「Canvas」というメッセージ・ボックスが表示される)。

  • 第2パラメータ(args):各イベントで定義される引数データ。例えば、Loadedイベントは引数が定義されていないので「null」となるが、MouseLeftButtonUpイベントでは「MouseEventArgsオブジェクト(=マウス・カーソルの位置を示すX軸とY軸の値)」の引数データになる(例えば「alert(args.x);」というコードを記述すれば、「<X座標の値>」というメッセージ・ボックスが表示される)。

 イベント・ハンドラ関数を実装したJavaScriptコードのサンプルは、次のページを参照してほしい。

 参考までに、“WPF/E”で利用可能なイベントも掲載しておこう。

イベント 説明 argsパラメータ
Loaded “WPF/E”コンテンツが“WPF/E”コントロールにロードされたときに発生する null
MouseEnter マウス・カーソルがオブジェクトの境界領域に入ってきたときに発生する MouseEventArgsオブジェクト
MouseLeave マウス・カーソルがオブジェクトの境界領域から外れたときに発生する null
MouseMove マウス・カーソルの位置が変化したときに発生する MouseEventArgsオブジェクト
MouseLeftButtonDown マウスの左ボタンが押されたときに発生する MouseEventArgsオブジェクト
MouseLeftButtonUp MouseLeftButtonDownイベントの次に、押されていたボタンが離されたときに発生する MouseEventArgsオブジェクト
MediaOpened 【MediaElementオブジェクトのみ】
メディアのロードが完了した際に発生する
null
MediaEnded 【MediaElementオブジェクトのみ】
メディアが終わったときに発生する
null
MediaFailed 【MediaElementオブジェクトのみ】
エラー(ファイルが見つからない/ファイル・フォーマットが不正/再生中の未知のエラー)になった場合に発生する
null
BufferingProgressChanged 【MediaElementオブジェクトのみ】
BufferingProgressプロパティが0.05以上変化する際に、1.0になるまで発生する
null
DownloadProgressChanged 【MediaElementオブジェクトのみ】
DownloadProgressプロパティが更新される際に、その値が1.0になるまで発生する
null
Completed 【Storyboardオブジェクトのみ】
タイムラインが完全に再生し終わったときに発生する
null
“WPF/E”で利用可能なイベント一覧
MouseEventArgsオブジェクトのxプロパティはマウス・カーソルのX座標を表し、yプロパティはY座標を表す。

 以上、(HTMLコード&AgHostオブジェクト関連&XAMLコードから)イベント・ハンドラまですべてを含めたコードを、次の.ZIPファイルにまとめた。

 ここまでで、“WPF/E”コントロールのロードから“WPF/E”のイベント処理まで、一通りの処理を見た。それでは次に、実際に“WPF/E”コンテンツを開発していく手順を見ていくことにしよう。

 ただし、現時点では“WPF/E”開発環境が完全にそろっているわけではなく、ツールを使った本格的な開発はできないと考えたほうがよいだろう。そこで以降では、開発のイメージを抱けるように画面を多用して開発の流れをざっと紹介するだけにとどめる。


 INDEX
  [Insider's Eye] “WPF/E”vs. Adobe Flash、ガチンコ対決!
    1.“WPF/E”の概要
    2.“WPF/E”とFlashの機能比較(ランタイム)
    3.“WPF/E”とFlashの機能比較(機能と制作)
         比較表. “WPF/E”とFlashの比較
   
  [Insider's Eye] “WPF/E”開発を体験してみよう!
    1.“WPF/E”が動く仕組み
  2.“WPF/E”の基本的な実装コード
        “WPF/E”のサンプル・コード
    3.“WPF/E”の開発(Visual Studio編)
    4.“WPF/E”の制作(Expression編)
 
 Insider's Eye


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間