Mark Davis, Heidi Housten, Dan Mohr, and Kusuma Vellanki
Microsoft Corporation
May 7, 2001
日本語版最終更新日 2001年6月25日
私たちチームにとっては見飽きたことです。少なくとも Heidi にはそうです。彼女は
私たちのふざけたちょっとした冗談を受け流すことができず、スウェーデンの Microsoft
Consulting Services に移籍しました。 冗談だよ、ね Heidi ! 彼女はストックホルムで
2 度目の春を楽しんでしましたが、彼女の銀行口座はかなり打撃を受けたようです。
果たしてすばらしいニュースなのでしょうか。これは私たち Web Team は、現在 1 日 16 時間働いているということを意味しています。これもすべて皆さんの質問をより適切に処理するためになのです。
今月は、Agent を紹介し、ソースの取得方法を説明します。さらに、言語間
にまたがった呼び出しやフレームの処理について少しお話します。私たちは、このチームで
働くことの危険や興奮に愛着を持っています。危険手当を求めたことはありませんが !
どうぞご質問を引き続きお送りください。でも、私たちが眠っている間に Heidi が忙
しくなるように、質問は早朝に送るようにしてください。質問は、
Web Team (英語で) に直接送ってください。
来月のコラムの話題を探しているときに、コラムのコメント セクションは調べたりしませんので。
では、本題に入りましょう !
目次
Dynamic HTA - 実行時に
セキュリティで保護されたフレームを表示する
XML の直接表示 - XML ソー
スを取得する
言語間にまたがる呼び出し -
言語間にまたがってスクリプト関数を呼び出す
Microsoft Agent の支援 -
Web ページの音声出力
Web Team の Q & A
Dynamic HTA
Web Team の皆さんへ
私は、イントラネットを HTML アプリケーション (HTA) に変換しています。しかし、問
題が 1 つあります。機能の 1 つは、操作する IFRAME タグと DHTML を生成するため
に JScript を使用して、サイト内で URL を開くことです。私はクロス フレーム スクリプトを
使用しています。そのコードを HTA 内に配置すると、失敗します。マニュアルには、これが
機能するためには APPLICATION="yes" 属性が必要であると記載されていま
す。そこで、私はその属性指定を Jscript 関数に追加しましたが、それでも機能しません。
その後、IFRAME 関数出力全体をコピーしたところ、正しく機能しました。詳しくテストして
みたところ、HTA 内で動的に生成された IFRAME タグが APPLICATION 属
性を処理していないことが分かりました。何か手順が不足しているのでしょうか ? それとも
この属性を認識するためにほかに設定する必要のある属性が存在しているのでしょうか ?
J. Wolfgang Goerlich
Web Team の回答
これは Internet Explorer 5.x での設計上の制限です。フレームのセキュリティの決定
は、ドキュメントが最初に解釈されるときに 1 度だけ行われます。ドキュメントの読み込み
が完了した後に動的に追加されたすべてのフレームは、APPLICATION 属性
が既定値の "no" になります。
この問題を回避する方法には 2 種類あります。
- Web アプリケーション フレームワークで、ドキュメントが解析されているときに、
どのフレームを表示するかを決定できる場合は、document.write を使って IFRAMES を動
的に記述し、その時点でフレームに設定されている APPLICATION 属性が有効に
なります。
- ドキュメントが読み込まれた後だけに決定を行うことができる場合は、ページ
内に非表示の IFRAMES を持ち、それを使用または再使用して、必要なコンテンツを位置決
め、表示します。
以下に、上記の回避策を説明するサンプル ファイルを示します。
Parent.hta
<HTML>
<HEAD>
<SCRIPT>
function SayHello()
{
alert("Hello there!");
}
function SetIframeSrc()
{
// ***** このファイル内のすべての localhost2 を異なるドメインに
// ***** 置き換えます。
document.all.ifrm1.src='http://localhost2/iframe.htm';
document.all.ifrm1.style.display='block';
}
</SCRIPT>
</HEAD>
<BODY>
これは、親 HTA です。子 IFRAMES が起動する関数を含んでいます。この HTA を 1 つの
ドメインに保存し、IFRAME ドキュメントを別のドメインに保存します。テストするためには、
この HTA 内の http://localhost2 を 2 番目のドメインに変更します。
<BR><BR> 親ドキュメント内の関数を起動できるかどうかを確認するには、
子 IFRAMES 内のボタンをクリックします。
<BR><BR><HR>
以下は APPLICATION=YES を持つ <B>動的な</B> IFRAME で、<B>document.write</B>
を使用して記述された別のドメインからのものです。
<BR><BR>
<SCRIPT>
document.write("<IFRAME SRC='http://localhost2/iframe.htm'
APPLICATION='yes'></IFRAME>");
</SCRIPT>
<BR><BR><HR>
以下のボタンをクリックすることにより、非表示の IFRAME の IFRAME SRC を設定し、
display スタイルを none から block に変更することにより、動的な IFRAMES を模倣します。
<BR><BR>
<INPUT type=button value="非表示 IFRAME の表示と新しい SRC の設定"
onclick=SetIframeSrc()>
<BR><BR>
<IFRAME id=ifrm1 SRC='about:blank' APPLICATION='yes'
STYLE='display:none'></IFRAME>
</BODY>
</HTML>
Iframe.htm
<HTML>
<BODY>
これは親の関数を起動するテスト ページです。
<BR><BR>
<INPUT type=button value="親関数の起動" onclick="parent.SayHello()">
</BODY>
</HTML>
XML の直接表示
Web Team の皆さんへ
私は、Microsoft Internet Explorer WebBrowser コントロール (Microsoft Internet
Controls) を使用する Microsoft Visual Basic アプリケーションを持っています。XML ペー
ジにナビゲートし、ソースを表示すると、オリジナルの XML が表示されます。しかし、document
オブジェクトにアクセスすると HTML を取得します。
WebBrowser コントロールからオリジナルの XML にアクセスする方法を教えてください。
Umashankar
Web Team の回答
これは Internet Explorer の既定の動作です。XML ドキュメントにナビゲートすると、
Internet Explorer は既定の XSL スタイル シートを使ってそのコンテンツを変換します。
Dynamic HTML オブジェクト モデルの一部である document
オブジェクトにアクセスすると、アプリケーションは生成された HTML を表すオブジェクトを
受け取ります。
都合のよいことに、 Internet Explorer は document オブジェクトに XMLDocument
expando プロパティを追加しています。これは、XML を折りたたみ可能な階層表示に変
換するだけでなく、オリジナルの XML へのアクセスも提供します。
詳細については、MSDN Online Web Workshop reference を
参照してください。
Dynamic HTML の作成者は Expando プロパティを使用して、オブジェクト モデルを拡
張することにより、既存のオブジェクトにプロパティを追加できます。また、一般的にスクリプト
プログラマは Expando プロパティを使用して、HTML エレメントやオブジェクトに詳細情報を
格納します。このプロパティは Visual BasicR アプリケーションで以下のように使用できま
す。
Private Sub Form_Load()
WebBrowser1.navigate " test.xml"
End Sub
Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
If (pDisp Is WebBrowser1.Object) Then
Dim doc As Object
Set doc = WebBrowser1.document.XMLDocument
MsgBox doc.documentElement.childNodes.length
End If
End Sub
C++ プログラマにとっては、Visual Basic が提供するほど簡単な方法はありません。C++
アプリケーションから XMLDocument expando プロパティにアクセスする場合は、直
接 IDispatchEx インターフェイスを使用することによりこれを行います。おそらくご存知のとおり、
IDispatch インターフェイスは公開しているオブジェクト メソッドやプロパティに対するサポートを
提供し、豊富なオブジェクト モデルを提供するために、Internet Explorer により広範に使用
されています。IDispatchEx インターフェイスは、オブジェクト モデルを動的にできる機能を提
供することにより、IDispatch インターフェイスを拡張します。Microsoft スクリプティング言語が
提供する expando プロパティを含めた優れた動的言語機能は、このインターフェイスが提供
します。
以下の コードは、C++ プログラマが CHtmlView 派生ビュー クラスを使用する Microsoft
Foundation Class (MFC) アプリケーションで XMLDocument expando プロパティに
アクセスする方法を示しています。サンプル コードは Microsoft Visual C++ COM コンパイラ
サポートを使用し、DocumentComplete はオーバーライドされた関数であることに注意してくだ
さい。
void CAView::DocumentComplete(LPDISPATCH pDisp, VARIANT* URL)
{
IDispatchPtr spDisp;
HRESULT hr;
hr = m_pBrowserApp->QueryInterface(IID_IDispatch, (void**) &spDisp);
// IDispatch* はトップ レベル ウィンドウ用に渡されましたか ?
if (pDisp == spDisp)
{
IHTMLDocument2Ptr spDoc;
// アクティブ ドキュメントを取得します。
spDoc = GetHtmlDocument();
if ( spDoc )
{
IHTMLWindow2Ptr spWin;
// トップ レベル ウィンドウを取得します。
spDisp = spDoc->Script;
spWin = spDisp;
if ( spWin )
{
// ドキュメントを取得します。
spDoc = spWin->document;
if ( spDoc )
{
IDispatchExPtr spDispEx;
// ドキュメントの IDispatchEx を取得します。
spDoc->QueryInterface( IID_IDispatchEx,
(void**)&spDispEx );
if ( spDispEx )
{
_bstr_t bstrName("XMLDocument");
DISPID dispid;
// XMLDocument expando プロパティを取得します。
spDispEx->GetDispID( bstrName,
fdexNameCaseSensitive,
&dispid );
if ( SUCCEEDED(hr) && dispid != DISPID_UNKNOWN )
{
VARIANT var;
DISPPARAMS dpNoArgs = {NULL, NULL, 0, 0};
// XMLDocument 値を取得します。
hr = spDispEx->Invoke( dispid,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYGET,
&dpNoArgs,
&var,
NULL,
NULL );
if ( SUCCEEDED(hr) && var.vt == VT_DISPATCH )
{
IXMLDOMDocument* pXMLDoc=NULL;
// IXMLDOMDocument インターフェイスを取得します。
var.pdispVal->QueryInterface(
IID_IXMLDOMDocument,
(void**)&pXMLDoc );
VariantClear( &var );
if ( pXMLDoc )
{
// ルート エレメントを取得します。
IXMLDOMElement* pXMLElem=NULL;
pXMLDoc->get_documentElement( &pXMLElem );
if ( pXMLElem )
{
BSTR bstr;
USES_CONVERSION;
// タグ名を取得/表示します。
pXMLElem->get_tagName( &bstr );
AfxMessageBox( OLE2T(bstr) );
pXMLElem->Release();
}
pXMLDoc->Release();
}
}
}
}
}
}
}
}
}
言語間にまたがる呼び出し
Web Team の皆さんへ
文字列を URLEncode から復元することが必要な VBScript ルーチンを私は記述していました。これを行う VBScript 関数が見つかりませんでしたが、JScript に "unescape"
関数が存在しているのを見つけました。私は、実際にこのルーチンを JScript に変換する
ことは望んでいなかったので、VBS 内で "unescape" 関数を使ってみたところ、機能しま
した !
これは正常な動作でしょうか ? ほかの Jscript 関数も VBScript で機能しますか ?
よろしくお願いします。
Ray Messinger
Web Team の回答
実際に、VBScript は escape 関数と unescape 関数を実装していますが、ドキュメントには記載されていません。ドキュメントに記載されなかった理由は、Web 開
発者はこれらの関数を URI のエンコーディングやデコーディングに使おうとすることがよくありま
すが、それがこの関数に実際に意図した機能を持たないないためです。たとえば、escape
関数を使うと、http://www.microsoft.com
内のコロン (:) がエスケープされますが、これは希望する結果ではないことに気付くでしょう。
この問題を解決するために、URI エンコーディング/デコーディング関数が ECMAScript に追加
されました。また、Microsoft の開発者は適切な URI エンコーディングとデコーディングだけを行う
以下のような簡潔で高性能の関数を実装するために力を注いできました。上記の主旨では、
escape 関数や unescape 関数ではなく、以下の関数を使用してください。
-
encodeURI
-
encodeURIComponent
-
decodeURI
-
decodeURIComponent
これらの関数は JScriptR だけで利用できることに注意してください。これでは、まだすべて
にお答えしたことになりませんね。幸いなことに、あなたのルーチンをすべて JScript に変換する必要
はありません。あなたが推測されていることは間違っていません。すべてのグローバル JScript 関数
またはすべてのユーザー定義 JScript 関数は直接 VBScript コードで呼び出すことができます。
VBScript 内から呼び出すことができるすべての組み込み関数の一覧については、
JScript ドキュメント を参照してください。
スクリプティングのドキュメントはスクリプティング サイトに
あります。これらの関数は JScript エンジンが読み込まれているときのみ利用できるので、ページ上に
JScript を使ったステートメントまたはブロックを最低 1 つ持つ必要があります。これは、以下のような
空のスクリプト ブロックでもかまいません。
<SCRIPT language=JScript> </SCRIPT>
OR
<INPUT type=button value="Say hello" onclick="JavaScript:alert('Hello')">
Microsoft Agent の支援 !
Web Team の皆さんへ
こんにちわ ! Microsoft Internet Explorer 5 を音声対応にする方法またはプラグイン
は存在するのでしょうか ? 私は音声コマンドを認識し、さらにテキストを声に出して呼んでく
れるブラウザを求めています。
Rebecca Robertson
マイクロソフトは Microsoft Agent テクノロジをサポート (つまり、アップデートおよび機能
強化) するつもりはあるのでしょうか ? その素材にはかなり楽しいものがあります。私は特に
Mr. Peedy が気に入っています。でも、ダウンロード証明書によれば、彼は現在まだほんの 2
才にすぎません。私は、彼が最適化されなかったり、将来のバージョンの Internet Explorer
で完全な互換性を持たないのではないかと懸念しています。どうか Mr. Peedy の翼をもがな
いでください !
David Hua
Web Team の回答
これまで、Microsoft Agent コントロールを使ってみたことがあれば、それが本当に役に立
つテクノロジで、とても楽しいものであることがおわかりでしょう。アクセシビリティに関する最初の
質問にお答えした後、Microsoft Agent について少し詳しくお話しましょう。
マイクロソフトは長年にわたりアクセシビリティの問題に取り組んできました。また、プログラム
やオペレーティング システムのアクセシビリティを強化する多くの機能を提供してきました。これら
の取り組み、機能、および製品の詳細については、Microsoft アクセシビリティ サイトをご覧ください。1 つの機能が
ナレータという音声合成 (TTS) ユーティリティで、Microsoft Windows 2000 で提供されています。
Internet Explorer 5 で提供されるアクセシビリティ機能は、http://www.microsoft.com/japan/enable/products/microsoft/ie5.asp
で紹介しています。
Internet Explorer Version 4.01 以降は、 Microsoft Active Accessibility をサポートする多くの製品の 1
つです。Microsoft Active Accessibility は、プログラムがアクセシビリティ支援と共に機能する方法
を強化する開発者テクノロジです。Internet Explorer での Active Accessibility サポートの詳細に
ついては、MSDN Online Web Workshop の Active Accessibility サポート ページをご覧ください。Internet
Explorer は、ユーザーが表示している Web ページ上のユーザー インターフェイスや HTML エレメント
に関するアクセシビリティ情報を提供します。アクセシビリティ支援は、ナビゲーション補助、視覚的な
補助、および音声合成補助を提供するためにこの情報を利用できます。
Microsoft Agent は健在です ! これは、アプリケーションや Web ページが、音声入力を受け付け
るだけでなく、音声合成機能を提供できるアニメーション効果を持つキャラクタを表示できるようにする
楽しいテクノロジです。このようなキャラクタは、Microsoft Office アシスタントの Clippy と同じように、アプリケーションの
ガイドやアシスタントとして動作できます。私たちは、Agent が最初にリリースされたとき、XML に変換
されたシェイクスピアの戯曲を大声で読み上げる Agent キャラクタを使った Web ページを面白半分に
作ってみました。このテクノロジの使用を制限するのはあなたの想像力だけです !
Agent が提供するキャラクタはオウムの Peedy、ロボットの Robby、Genie、および Merlin で、それ
ぞれのキャラクタは広範なジェスチャのリストを持っています。また、Microsoft Agent Character Editor
を使って独自のキャラクタを作成できます ! キャラクタの同期やイベントなど、利用可能なプログラミング
機能が多数存在します。さらに、このテクノロジを ActiveXR コントロールおよびプログラミング可能
なオブジェクトとして利用できます。詳細については、Microsoft Agent Web サイトの開発者ドキュメントをお読みください。このサイトは、
Microsoft Agent テクノロジ、開発者ドキュメント、およびサンプル コードのダウンロードを提供します。
最後に、Web ページのタイトルを音声で読み上げる簡単な音声合成機能を提供する Agent を
使うカスタム ブラウザの開発方法を例示する Microsoft Foundation Class (MFC) サンプル コードを
示しておきます。この例を応用して、Web ページ全体を読み上げる機能、選択したテキストを読み上
げる機能、または Web ブラウジングを制御する音声入力を受け付ける機能も作成できます。
以下の手順は、Agent テクノロジと Peedy キャラクタがインストールされていることを前提としてい
て、Microsoft Visual C++R 6.0 AppWizard を使用して作成した標準 MFC アプリケーションを基
にしています。ウィザードの最終画面で、Internet Explorer WebBrowser ビューを実装する CHtmlView
ビュー クラスを選択します。アプリケーションを作成後、Visual C++ [プロジェクト] メニューの [プロジェク
トへ追加]-[コンポーネントおよびコントロール] メニュー項目を選択し、プロジェクトに Microsoft Agent
Control 2.0 クラスを挿入します。
- プロジェクトに Agent コントロールを挿入したときに生成された以下のインクルードを、
ビュー クラスのヘッダー ファイルに追加します。
#include "agentctlex.h"
#include "agentctlcharacters.h"
#include "agentctlcharacterex.h"
#include "agentctlrequest.h"
- ビュー クラス定義の内部で、以下のクラス データ メンバとメソッド定義を追加します。
CAgentCtlEx m_AgentCtl;
CAgentCtlCharacters m_AgentCharacters;
CAgentCtlCharacterEx m_AgentCharacter;
void DocumentComplete(LPDISPATCH lpDisp,VARIANT FAR* URL);
- ビュー クラスのオーバーライドした OnInitialUpdate() に、Agent コントロールを
初期化するために、以下の太字のコードを追加します。
void CMyView::OnInitialUpdate()
{
CHtmlView::OnInitialUpdate();
// Microsoft Agent コントロールを作成します。
m_AgentCtl.Create( "msagent", WS_VISIBLE, CRect(), this, ID_AGENT );
m_AgentCharacters = m_AgentCtl.GetCharacters();
// Peedy キャラクタを読み込みます。
m_AgentCharacters.Load( "peedy", _variant_t("peedy.acs") );
m_AgentCharacter = m_AgentCharacters.Character( "peedy" );
// Peedy を表示します。
m_AgentCharacter.Show( _variant_t() );
// TODO: 次のコードは Web で人気のある場所にナビゲートします。
// 好みに応じてコードを変更してください。
Navigate2(_T("http://www.microsoft.com/visualc/"),NULL,NULL);
}
- OnDocumentComplete イベントを処理するために、
CHtmlView::DocumentComplete() メソッドをオーバーライドします。
void CMyView::DocumentComplete(LPDISPATCH lpDisp,VARIANT FAR* URL)
{
IUnknown* pUnk;
IDispatch* lpWBDisp;
BSTR bstrTitle;
HRESULT hr;
hr = m_pBrowserApp->QueryInterface( IID_IUnknown,
(void**)&pUnk );
hr = pUnk->QueryInterface( IID_IDispatch,
(void**)&lpWBDisp );
if ( lpDisp == lpWBDisp )
{
IDispatch* lpDocDisp;
IHTMLDocument2* lpDoc;
// トップレベル Window オブジェクトなので、ドキュメントが読み込まれました。
lpDocDisp = GetHtmlDocument();
hr = lpDocDisp->QueryInterface( IID_IHTMLDocument2,
(void**)&lpDoc );
lpDoc->get_title( &bstrTitle );
// "greet" ジェスチャを指定します。
m_AgentCharacter.Play( "Greet" );
// Web ページのタイトルを読み上げるように Peedy に依頼します。
m_AgentCharacter.Speak( _variant_t( bstrTitle ), _variant_t() );
lpDoc->Release();
lpDocDisp->Release();
}
lpWBDisp->Release();
pUnk->Release();
}
Web Team の Q & A
XML/XSL と Microsoft.com
Q: XML と XSL を使った www.microsoft.com の再構築に関する MSDN の
記事を探しています。 (Russ Darroch)
A: この記事です。XML と www.microsoft.com
ビヘイビアのパラメータ
Q: DHTML ビヘイビアのパラメータを省略可能にできるかどうかを教えてください。 (Phil Jones)
A: JScript では可能です (関数内部の arguments プロパティを調べてください)。
ただし、VBScript ではできません。
WebBrowser コントロールとスクリプト関数
Q: Visual C++ から WebBrowser コントロール内のスクリプト関数を呼び出す方法を
教えてください。 (Dax Westerman)
A: 詳細については、Q185127 - HOWTO: Call a Script Function from a VC WebBrowser Application
を参照してください。
表示更新と実行時間の長いスクリプト呼び出し
Q: 実行時間のかかるスクリプトを呼び出しているときに、表示を更新する方法を教えて
ください。 (Bo)
A: Dave Massy が彼の記事 DHTML Dude 「時間がかかる操作中に表示を更新する」でこの疑問に取り組んでいます。
Web Team
Mark Davis は、Internet Explorer SDK team のソフトウェア デザイン エンジニアです。Mark はもともとイングランド出身で、最近は北西部の名峰に挑戦するためのトレーニングをしています。
Heidi Housten は、MSDN Architectural Samples チームのメンバです。Heidi は Microsoft Developer Support の Internet Client チームから MSDN へやってきました。英国で 14 年間を過ごした Heidi は、英国での生活はシアトルの曇り空と霧雨に対する準備期間だったと納得しています。
Dan Mohr は、マイクロソフト開発者向けサポート Internet Client チームのエンジニアです。
時間があるときは、彼の地下室でバンドの録音をしたり、Commodore 64 のプログラミングをしたり、
70 年代後半のパンク ロックの長所を激賞したりしています。
Kusuma Vellanki は、ワシントン州の冬が夏よりも好きだという数少ない人間の 1 人です。Internet Client チームの Developer Support Engineer である Kusuma ですが、勤務時間外にはスキー場で張り切って滑っている姿が見られます。