きのう HTMLWindows5 インターフェースの件で煮詰まっていると書いてしまった。 ひょっとしたら検索エンジンでここに迷い込む人もいるかもしれないので、少しは役にたちそうな情報を書いておくことにした。(笑)
// (注意)エラー処理や、リソースの開放などまったく省いてあります
// mshtml.h は Visual Studio 2008 Bata2 のインストールで得られる
// 2007年8月時点で最新のものを使っています
// IE7 で実装された機能なので、 IE6 の環境では使えないと思います。
// Visual Studio 2005 で動かすには、その他に下記の定義も必要でした
/*
static CLSID const IID_IHTMLWindow5
   = {0x3051040e,0x98b5,0x11cf,0xbb,0x82,0x00,0xaa,0x00,0xbd,0xce,0x0b};
static CLSID const IID_IHTMLXMLHttpRequestFactory
   = {0x3051040c,0x98b5,0x11cf,0xbb,0x82,0x00,0xaa,0x00,0xbd,0xce,0x0b};
static CLSID const IID_IHTMLXMLHttpRequest
   = {0x3051040a,0x98b5,0x11cf,0xbb,0x82,0x00,0xaa,0x00,0xbd,0xce,0x0b};
*/

IHTMLWindow5* pWin5;
IHTMLXMLHttpRequestFactory* pFac;
IHTMLXMLHttpRequest* pXml;
IHTMLWindow2* pWin;
IHTMLDocument2* pDoc;
IDispatch* pDisp;
VARIANT pVDisp;

// IHTMLDocument2 を得ます、今回は下記二行のようにしました
pDisp = m_ctrlWebBrowser.get_Document();
pDisp->QueryInterface(IID_IHTMLDocument2, (void** )&pDoc);

// IHTMLWindow5 を得ます
pDoc->get_parentWindow(&pWin);
pWin->QueryInterface(IID_IHTMLWindow5, (void** )&pWin5);

// 下記が解りにくい、他に方法があるのかも?
pWin5->get_XMLHttpRequest(&pVDisp);
pVDisp.pdispVal->QueryInterface(IID_IHTMLXMLHttpRequestFactory, (void** )&pFac);
pFac->create(&pXml);

// ここからXMLHttpRequestが持っているメソッドは何でも使える...はず
//pXml->getAllResponseHeaders
//pXml->get_responseText など、など
ボクとしては、すでにナビゲートしたページのResponse Headers を取得したかったのだけれど、上記の機能は、新しく生成した IHTMLXMLHttpRequest インターフェースから サーバーにリクエストを出す、というAjax的な使い方を想定しているようだ。 残念...

 しばらくはいじるつもりがなかったのに、Visual Studio 2008 Beta2をVistaにインストールしてしまった。

 IHTMLWindow5 インターフェースの件で煮詰まっていて、ひょっとしたら、2008 Beta2 ではうまく動いているのではないかと思ったからだ。

 C#ではやはり、オブジェクトブラウザにこのインターフェースは現れず断念。 最新の mshtml.h で IHTMLWindow5 の定義を見つけたので、C++から動かしてみた。

 結果、IHTMLWindow5 インターフェースを得ることは出来たが、MSDNで解説されている XMLHttpRequest Member を得ることは出来ていない。 Google様でさえ、有用な情報を漏らしてくれない状態ではお手上げかも? すっきりしないなぁ(涙)

08/11/2007 10:7 AM

こんにちは、Visual Studio 2008 Beta2はだれでもDL出きるんですね。Express のURLかっこいいですね。Framework 3.5でWPFの凄いの動かしてみたいですがまず グラフィックカードの良い物を捜さなくては。

スー

08/11/2007 10:54 AM

スーさん、こんにちは。 ボクのVista マシンのグラフィックはオンボードのものなので最悪。 やっと動いているというスピードです。 早いPCが欲しいなぁ。

本人

インターネットエクスプローラ上で新しいウインドウを開くことを止める方法についてぐぐってみると、いろいろな情報が見つかる。
NewWindow2イベントを補足して新しいIEの中のBeforeNavigate2イベント内でもとのIEにNavigeteするもの...その他いろいろ。
しかし、ボクの現在の環境では動きがおかしい、ずっとIEを制御してゆきたいのに、どこかで家出されてしまう。

http://msdn2.microsoft.com/en-us/library/aa768288.aspx
を見てみると、どうもこのイベントを使って処理をするのが良いようだ。

ボクが制御したいのは、new InternetExplorer(); したものなので、Form に張りつけたコントロールとはちょっと違ってハンドラのパラメータが特殊だ。 コントロールのハンドラのパラメータは axWebBrowser1_NewWindow3(object sender, AxSHDocVw.DWebBrowserEvents2_NewWindow3Event e) とすっきりしている。 でも、当然のことながら参照するものがForm上のWebBrowserコントロールでない場合はこの引数ではコンパイルできない。

結果、new InternetExplorer(); した場合のイベントハンドラの引数の書式は下記のようになる。
static void OnNewWindow3(ref object Object, ref bool Cancel,
                          uint Flags,  string strContext, string strUrl)
{
  // 手抜き
  object vPost=null, vHeaders=null, vFlags=null,
               vTarget=null, vUrl=strUrl;
  // ここで ie とは InternetExplorer オブジェクト。ボクはnew で作成した。
  ie.Navigate2(ref vUrl, ref vFlags, ref vTarget, ref vPost, ref vHeaders);
  Cancel = true;
}
これで、新しいウインドウが開くことを抑制し、自分自身のウインドウ内で新しいURLを表示するはず。 少なくともボクの環境では動いている。 (Windows XP SP2 + Visual Studio 2005 SP1 + IE7)

08/04/2007 2:30 PM

こんにちは、家出されては困りますね、この辺になるとC++ですか?
暫くはIE6との付き合いです。

スー

08/04/2007 6:1 PM

スーさん、こんにちは。 古いバージョンのC++で書くと、大変な行数のプログラムになってしまうことと、変なことをやろうとすると情報が少なすぎて、手におえません。(汗) C# ですよ...ref とかありますから。

本人

process = Process.Start("iexplore.exe", "http://niseko.or.jp");
//process = Process.Start("notepad.exe", @"c:\test.txt");
process.WaitForInputIdle();
こんな簡単なコードで外部プログラムが起動できるので便利(一番上の一行だけでOK)だが、なぜか process.MainWindowHandle にウインドウハンドルが入らない。 コメントアウトしてあるが、たとえば メモ帳などを起動した時は、ハンドルをきちんと取得出来るので、IE の問題だと思う。
IHTMLDocument2 doc = null;

Shell sh = new Shell();
ShellWindows win = (ShellWindows)sh.Windows();
foreach (Object obj in win)
 InternetExplorer ie = (InternetExplorer)obj;
 doc = (IHTMLDocument2)ie.Document;
 Type t = doc.GetType();
 if (t.ToString() == "mshtml.HTMLDocumentClass")
 {
  int id = 0;
  int dwThreadID = GetWindowThreadProcessId((IntPtr)ie.HWND, ref id);
 }
}
幸い、process.Id は取れるので、上記のいんちきコードで起動しているIEを探すと該当するもの(プロセスIDが同じ)がすぐ見つかる。 ウインドウハンドルもすぐ手に入る。 当然のことに、ウインドウハンドルが無いなんてーぇわけがない...

いや、何の意味もない独り言です。

08/02/2007 9:49 AM

こんにちは、blog2になってから3年も経ったんですね。
遡って見てしまいました。インターネットエクスプローラの不思議 を

スー

08/02/2007 2:14 PM

スーさん、こんにちは。
最近プログラミングの話題を書かなくなりました。
いろいろいじってはいたのですが、書くような気分ではなかったのです。
また、環境が変わりつつありますので、バリバリ書くかなぁ。(笑)

本人

 2001年の始め頃に書いたHTMLを動かしてみた。 DHTMLをガリガリ使っているし、IE以外でテストした記憶もないので動かないだろう、という妙な確信があった。

 Firefoxで起動したら、やっぱり動かない。 FireBUGの画面と相談しながらソースの修正をする。
 やっぱり
parent.frames[0].hogehoge.innerHTML = ””;
なんて書いてある。

 最初は、frame に名前を付け
parent.frames['hoge'].getElementById('hogehoge').innerHTML = ””;
でアクセス出来るかも?と思ったけれど、FireBUG は
parent.frames.hoge has no properties
と、怒っている。

 IEでは一番上の記載から想像したくなるように
parent.frames[0] は Document を示しているように思っていた。 しかし、
parent.frames['hoge'] はやっぱり frame オブジェクトとした方が自然。

parent.frames['hoge'].document.getElementById('hogehoge').innerHTML = "";
で無事動作を確認する。

IEの表記って便利だったけど、今となってはどうなんでしょうね?

07/15/2007 3:58 PM

こんにちは、ソースの修正ということは時間に余裕が出てきましたか?。DOMの階層をすっかり忘れてます。

スー

07/15/2007 6:25 PM

スーさん、こんばんは。
時間に余裕が出来たのではなく、ストレスと頭痛でクリエーティブな仕事は出来ないのです。 単純なソースを直すくらいがちょうど良いリハビリ?
ちょうど、EzoTanukiさんが、思い出したようにセールスしてみようと言い出したので、古いJavaScriptのソースやら、iアプリのJavaソースなどを引っ掻き回しています。(笑)

本人

 腰は少し回復したものの、妙な「風邪」に取り付かれたらしい。 大変体調が悪い。

 インタネットエクスエクスプローラをこづきまわして遊ぶ。 ついでに、どうしてものどに刺さった骨状態の OleDraw() をいじる。 CoCreateInstance()で作成した"InternetExplorer.Application"でOleDraw() が動作しないという不思議。 Window として Createしたものでは問題なく動くので、COMオブジェクト独自の問題なのかもしれない。

 どこかでとんでもない思い違いをしているのかも? 画像は正常に動く OleDraw()。 Window の左上にサムネール状態で書き込んでいる。 修行が足りない...

05/02/2007 1:10 PM

こんにちは、腰を痛めていたのですか?、風邪も早く直してください。COMオブジェクトの階層くらいしか理解していません、こんなにも沢山の技術は、....です。

スー

05/02/2007 2:18 PM

スーさん、こんにちは。 一人なので、調子が悪くてもやることはやらねばなりません。 風邪もなかなかしぶとく、治りません。 健康が一番ですね。

本人

 テストの時とサブスクライバダウンロードの時しかインターネットエクスプローラは使わない。 で、気がつかなかったのだけれど。 CSS要素の padding が効かない組み合わせがある。 padding の指定はいろいろな方法があるけど、試してみた範囲ではどれも駄目。(汗)

 画像左側が IE7 右側が Firefox。  Opera も大丈夫。 かなり見栄えが違う。
     .box {
       border-style: solid;
       border-color: gray;
       border-width: 1px 3px 3px 1px;
       padding: 3px;
     }

03/28/2007 8:58 AM

確かインターネットエクスプローラでもこのタイプのシャドーボックスを見た記憶があるので調べてみた。
「文書型宣言」で各ブラウザの処理が違うんだね。
Transitional DTD の文書型宣言をつけてみたら、インターネットエクスプローラでも Padding をきちんと処理してくれるようになりました。 (ホッ!)

本人

03/28/2007 10:46 AM

こんにちは、朝5時から仕事でした、CSSにはなかされた経験があります。Alige_auto とか width,High とかブラウザ同士で見た目が違うとか、URLをつけた標準モード以外はとか、条件をつけたくなります。

スー

 Windows Vista 上の IE7 を Internet Explorer 7+ と呼ぶ んだそうだ。

 実際にVISTAをインストールし、動かしてみると、本当だった。 USER AGENT が「 Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; MSDigitalLocker Vista 1.3; SLCC1; .NET CLR 2.0.50727; WinFX RunTime 3.0.50727)」 と表示される。 VISTA って Windows NT 6.0 だったのね? (笑)

06/04/2006 8:18 AM

Office 2007 のベーターは、今月届きますが、Vistaはもうチョット先です。

スー

 イージーにインターネットエクスプローラかどうかを
if (document.all) 
で判断していたが、Opera ではそれが効かない。 Opera の UserAgent は
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.0
これは殆どインターネットエクスプローラだ...

インターネットエクスプローラのUserAgent は一般的に
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) この後にいろいろ続く...

 というわけで、ブラウザの判別は
if (navigator.userAgent.indexOf("MSIE")  != -1
   && navigator.userAgent.indexOf("Opera 8.0") == -1)
ということになったが、これでも完璧に!不完全だ。 なかなか大変なんだなぁ。

そんなことより...
Opera version 8 でこのBlogが表示出来ないことが発覚した。 面倒だけれど直すか。 (涙)

 アドレスバーに直に入力する場合を除くと後はスクリプトで処理できるケースなので下記のようにコードを修正することによって、インターネットエクスプローラでもUTF-8としてURLエンコードさせることが可能なようだ。
 xmlhttp.open('GET', encodeURI(strURL), true);
 このコードはWindows版のFirefoxにそのまま渡してもすでにUTF-8でURLエンコードされているわけだから影響は出ないようだ。 これで二つの環境で同じ動作を期待できる。 Opera version 8 でも試してみよう。

 それにしても、インターネットエクスプローラにUTF-8のコードを渡しているのに、Shift_JISに変換してエンコードなしに送るとは...過去の動作との互換性のためなのか?

05/24/2005 9:10 AM

おはようございます。明日からは良い天気とのこと、期待します。
アンドキュメンテッドIE版のようですね。リアルモニターで1つ1つ検証して次に進むですね。変換する、しないのSWみたいのって無いですかね。解決策があって良かったです。まさか徹夜で無いですよね。昨日いしだの秘密基地をみてしまった、Hさんのライブカメラまでも。

スー

05/24/2005 11:29 AM

 スーさん、こんにちは。 結婚式のオンデマンドビデオを見ましたか...リアルタイムに配信していた時、30人以上の人が見ていたようです。 すごい時代になってきましたねぇ。

本人

 たとえば、アドレスバーで、
http://hogehoge.doka/hoge.cgi?para=漢字
のパターンでアクセスすると、インターネットエクスプローラでは「漢字」の部分もエンコードされずそのまま送られる。 Windows 上の Firefox などでは、シフトJISコードとしてURLエンコードされて送られる。

下記のコードでJavaScriptからアクセスすると...
  function getCode(strURL) {
    if (document.all) {
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    else {
      xmlhttp = new XMLHttpRequest();
    }
    if (xmlhttp) {
      xmlhttp.onreadystatechange = response;
      xmlhttp.open('GET', strURL, true);
      xmlhttp.send(null);
    }
  }

getCode("/hogehoge.cgi?param=漢字");
という呼び出しをすると、インターネットエクスプローラでは上と同様URLエンコードされないで送られる。
 Windows 上の Firefox では UTF-8 としてURLエンコードされて送られる。

 JavaScript を呼び出しているページの charset が utf-8 でも Shift_JIS でも動作は変わらない。 これでは...呼び出されるCGI プログラムの中での処理が大変だ。 いっそ、パラメータには2バイトコードを使わないようにするか。 いや、そうじゃなくて、スマートな解決策はないのかなぁ???

ASP.NET 2.0 でスクリプトコールバックという仕組みが動くと言われているけど、この辺の2バイトコードの扱いはどうなっているのだろう。 時間を作って調べてみなくては。

 HTML ファイルを渡して Fax してもらう仕組みのこと、いよいよ複雑なレイアウトにして画像や外部ファイルを読み込んでみた。 予想していたから驚かないけれど、絶対パスか base href タグを書かなくては読み込めない。

 同じファイルをダブルクリックで起動したり、エクスプローラからドラッグアンドドロップすれば、自分自身を基点としてきちんと解釈してくれるわけだから、混乱の元だ。 こんなことでいらいらしているのはやはり、ボクだけなのか...(笑)

 普段あまり見ないページを Firefox で見た。 突然! HTML の内容がタグ付きで表示された。 インターネットエクスプローラで見ると問題がない。 ブラウザが受け取ったソースを見てみるが、問題は見つからない。 作成者に電話すると、Firefox って「がっさい」(方言?) んじゃない? と言う話に落ち着いた。

 でも、CGI のソースを送ってもらい、隅から墨まで目を通してみた...不思議だからねぇ。 問題が発生しそうな部分は見つからない。 気を取り直して、幽玄の彼方に旅をしてみる。 CGI のソースをエディタで開き直す。 あった! print "Content-type: text/plain\n\n";  いままで普通に表示されていたので、この行は無意識に読み飛ばしていた。 plain って書いてあるんだから、そのまま表示するのが正しいよね。 パケットのログも読み直してみたら、ヘッダーにContent-Type: text/plain が付加されて送られて来ている。 Firefox さん、疑ってごめんなさい。 ボクはあなたの解釈が正しいと思います。 

 ぐぐってみたら、このインターネットエクスプローラが内容を見て勝手にHTMLだと解釈する...というのは有名な話みたいですね。 親切と言えば、そのとおりだけれど...(笑)

03/18/2005 7:57 PM

今晩わ、コンピーターの学習機能は怖い物がありますね。
シンプル イズ ベスト の方が良いですよね。
EPSON CD ROM 1
USB ケーブル  1
説明書       1
フイルム トレイ  4
を お渡ししました。ドライバーをインストールして動作確認しました。

スー

03/18/2005 8:14 PM

 スーさん、こんばんは。 お世話になりました。 納期が迫っているのに、基幹となるPCが故障してしまい、大変なことになりそうだったのです。 助かりました。

本人

 Firefox でIIS にアクセスすると不思議なことが時々起こる。 すぐその場でインターネットエクスプローラから同じことをやってみると、問題は再現しない。 パケットをキャプチャーしてみたが、URL の後ろの GET 用のパラメータは無事送出されているようだ。

       http://hogehoge.jp/hoge.exe?df=para.dat&dd=C|ft=0 という呼び出しだ。

       きちんと GET /hoge.exe?df=para.dat&dd=C|ft=0 HTTP/1.1 という呼び出しに変換されている

 1996年頃から動いているアクセスカウンターを呼び出すCGI である。 ソースコードを引っ張り出して中身を読んでみると、QUERY_STRING がCGI でうまく取れないのがエラーの原因のようだ。 試しに、インターネットエクスプローラで

       http://hogehoge.jp/hoge.exe

 で呼んでみると、Firefox で呼んだのと同じエラーが起こる。

 RFC を読んでみると
   Other characters are excluded because gateways and other transport
   agents are known to sometimes modify such characters, or they are
   used as delimiters.

   unwise      = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"

   Data corresponding to excluded characters must be escaped in order to
   be properly represented within a URI.
 やはり、"|" が原因なのだろうか? それにしてもインターネットエクスプローラからアクセスすると問題が起きないのはなぜだろう? Firefox でエラーが起きるのはいつもというわけではないが...IIS がブラウザを見て「えこひいき」 していると考えるのは、読みすぎだろうか? そんなことないか! (笑)

 いずれにしても

       http://hogehoge.jp/hoge.exe?df=para.dat&dd=C%7Cft=0

 とすべきなんでしょうねぇ。

 タイトルの二つは、同じURL を扱うには同じ動作だろうと思いますが、実際にはちょっと違う動きをします。 インターネットエクスプローラのキャッシュの設定を見てみましょう。 「ツール」メニューから「インターネットオプション」を選び、表示されたダイアログの「全般」タブの「インターネット一時ファイル」の中の「設定」 ボタンを押します。



 この中で「自動的に確認する」 の設定になっている場合、window.location.reload() は曖昧な動作をします。 何度かリロードを繰り返しているうちに



 上記のダイアログが出ます。 このダイアログの出方が曖昧に出るような感じがします。 window.location = 'http://hoge.jp/' では、何度繰り返してもボクの環境では出ません。 forms[?].submit() や window.location でロードし直せばダイアログは出ないのでOK なのですが、ぐだぐだ書いているのは、単に不思議 だからです。 動かしてみているのは、インターネットエクスプローラ 6 SP1 の環境です。

 ブラウザのキャッシュを制御する にブラウザのキャッシュの問題が詳しく書かれていますが、今回のケースの、この曖昧に出るダイアログの問題とは直接関係はないようです。

 一般的にそんなケースはあまりないのでしょうが、二つに分かれたフレームの右側のページが動的に変わり、そのページを左側のページから強制的にリロードさせようとして、このダイアログにぶつかりました。 このケースでは window.location = 'http://hoge.jp/' では、呼び込むCGI ファイル名が動的に変化するので管理が大変です。 しかし、CGI のページでは forms[?].submit() が動くので、運営上は何も問題はありません。

 submit() されるページがCGI でなくても (たとえば、HTMLファイルでも)
 <form action='/hoge.htm' method='GET'>
 </form>
 が入っていれば、submit() 出来ます。 ただし、method は GET しか動かないようです。 これは、仕様なのかバグなのか? ボクには解りません。 (笑)

12/03/2004 11:22 PM

道南?
私はどこにも行きませんが・・・・・・

EzoTanuki

12/04/2004 8:44 AM

 EzoTanuki さん、お久しぶりです。 かなり忙しかったようですね。 たぶん「道南」 は nyo2 さんの Blog から来たのだと思います...
 Pocket PC による簡易POS を模索中です。 EzoTanuki さんの仕事が一段落したところで連絡をとろうと、書き込みを待っておりました。 興味ありませんか?

本人

 実は、昨日の話は、今回の話の副産物である。 ベーシック認証のページにアクセスすると、ユーザー名とパスワードを求めるダイアログが表示される。 これでは、何かを自動化させようとする時、このダイアログが妨げになる。 まあ、何を自動化させようとするのか...そんな要求はないのかもしれないけれど、やってみた。

 var IE = new ActiveXObject("InternetExplorer.Application");
 IE.Visible = true;
 // ユーザー名とパスワードを <:> でくくり、Base64 でエンコードしたものを送る
 // 下記は user:password の例である
 strHeader = "Authorization: Basic dXNlcjpwYXNzd29yZA==\r\n"
 IE.Navigate2("http://www.hoge.jp/hoge.pl", "", "", "", strHeader);

 スクリプトによる、Base64 の処理に関しては、 VBScript で BASE64 の処理をする (unibon) 高度な JavaScript 技集 などにある。 昔、この「高度な JavaScript 技集」 をはじめて見た時はかなりインパクトがあった。 必見である。

11/25/2004 9:16 PM

今晩は、時間がいくら有っても足りないぐらいの情報量です。
伊勢さんのページでも何ヶ月かかるやら。
どんどん膨張する宇宙で外周の規模は、見当が付かない。

スー

11/25/2004 9:39 PM

 スーさん、こんばんは。 数年前に、DBF ファイルの年号フラッグ問題があった時、ファイルの頭の数バイトをスクリプトから書き換えようとして断念しました。 スクリプトのファイルシステムではバイナリーの読み書きが出来なかったからです。
 ADO.Stream を使えば出来そうな気がしてきました。 バイナリデータのBase64 デコードも断念していますが、そのうち、再挑戦してみます。

本人

 [InternetExplorer.Application] または [IWebBrowser2] の Navigate2 メソッドでは、ヘッダー部分の書き換えが可能だ。 無いものは新規に追加され、同じ名前のものは上書きされる仕様のようだ。

 この Navigate2 の第5引数に [Content-Type: application/x-www-form-urlencoded] を与え、第4引数に POST で送りたいデータを指定すると、POST リクエストが送られる...という記載が Microsoft のサイトをはじめ多くのホームページに載っている。 この第4引数が PostData As Variant と書かれていることから、第5引数と同じタイプのパラメータで大丈夫だと思いがちである。

 しかし、其のパターンでは、ヘッダーに Content-Type: ...は付加されるが、なぜかMethod は GET で送られてしまう。 ここで、はまってしまうのはボクだけだろうか...  Microsoft のNavigate2の説明 の最後の方に [Array and point to a SAFEARRAY Data Type] という言葉が出て来る。 配列の形でパラメータを与えなければ、何が何でも GET になってしまうようだ。 解りにくい...

 'VBScript
 Dim bDATA, strHeader
 Set Stream = CreateObject("ADODB.Stream")
 Stream.Open
 Stream.Charset = "Shift_JIS"
 Stream.WriteText "name=漢字"
 Stream.Position = 0
 Stream.Type = 1
 bDATA = Stream.Read
 Stream.Close
 Set Stream = Nothing

 Set IE = CreateObject("InternetExplorer.application")
 IE.Visible = True
 strHeader = "Content-type: application/x-www-form-urlencoded" + vbCrLf
 IE.Navigate "http://www.hoge.jp/hoge.pl", , , bDATA, strHeader


 // JavaScript
 var bData, strHeader;
 var Stream =  new ActiveXObject("ADODB.Stream");

 Stream.Open();
 Stream.Charset = "Shift_JIS";
 Stream.WriteText("name=hoge&work=仕事");
 Stream.Position = 0;
 Stream.Type = 1;
 bData = Stream.Read();
 Stream.Close();

 var IE = new ActiveXObject("InternetExplorer.Application");
 IE.Visible = true;
 strHeader = "Content-Type: application/x-www-form-urlencoded\r\n";
 IE.Navigate2("http://www.hoge.jp/hoge.pl", "", "", bData, strHeader);

 Microsoft のサンプルが、 "Content-Type: application/x-www-form-urlencoded\n\r"; と書いてあるせいか、そのまま、 \n\r と書いてあるホームページをいくつか見かけた。

11/25/2004 9:24 AM

JavaScriptの書式のほうがC#に近いが仕組みが違うので
別物なのだけれども同一視したくなる。複数言語は困ってしまうが良いとこ取りも出来ないし。複数言語はメモ、めも
vbCrLf は解りよいのはなぜなのかなー。

スー

11/25/2004 10:29 AM

 スーさん、おはようございます。 C, C++, Java, C#, J++ などで、 \r\n という記載は無意識に書いてしまいますが、VB や VBScript では、まともに書くと、 chr(13) + chr(10) などと書かなければなりません。 vbCrLf の定義があるのは、とても助かります。 と言っても、めったに VBScript は書きませんが...

本人

 インターネットエクスプローラのDOM に慣れすぎてしまったせいか、つまらないところではまる。

 インターネットエクスプローラなら
     parent.frames[1].msg.innerHTML
 で参照出来ていたのに、Firefox では
     parent.frames[1].document.getElementById("msg").innerHTML
 だもんね。

 しかし、Firefox の 「JavaScriptコンソール」と「DOMインスペクタ」は強力だ。 ぺろ! っとなめただけなのにもう離れられないノーミソになってしまった。 (笑)

 今回はちょっと変わっている。 最初にXMLファイルを読み込ませる。
var IE = WScript.CreateObject("InternetExplorer.Application");
IE.Visible = true;
IE.Navigate('d:\\WorkSpaceD\\WB2\\Release\\a.xml');
while(IE.busy);
while(IE.Document.readyState != 'complete');
IE.Navigate2("JavaScript:" + "\"" + "<html><body><img
src='ok.gif></body></html>" + "\"")
 やはり、画像は表示出来ないが、右ボタンクリックでソースを表示してみると...
"<HTML>"<SCRIPT LANGUAGE=javascript>var __w=""<html>"<body>"<img
src='ok.gif'>"</body>"</html>";if(__w!=null)document
.write(__w);"</SCRIPT>"</HTML>
 いったい誰が、 document.write しているんだろう? ボクは覚えがないゾー
 最初の Navigate で HTML ファイルを読み込ませた場合は、右ボタンクリックのソース表示で、JavaScript: 以下の記載がそのまま出て来る。 やはり画像は表示出来ない。 その画像のプロパティを見ると、
javascript:"<html><body><img%20src='ok.gif'></body></html>"ok.gif
 これでは、画像を読み込めるわけがない。
 document.write を責め続けるのはそろそろ止めて、そんなものだと諦めよう...(笑)

 インターネットエクスプローラの不思議 その 2で使ったスクリプトがWSHのものだから、カレントディレクトリがWSH管理のものとなり、読み込みに失敗するのではないか? との情報あり。
var IE = new ActiveXObject("InternetExplorer.Application");
IE.Visible = true;
IE.Navigate('about:blank');
while(IE.busy);
while(IE.Document.readyState != 'complete');
IE.Document.write("<html><head><title>hoge</title></head>
  <body><b>hoge</b><br><img src=hoge.gif></body></html>");
とやってみるが、結果は同じ。

 カレントディレクトリの問題なら...とC++でむりやりコーディングしてみる
  • レジストリからインターネットエクスプローラの実行ファイルのパスを得る。


  • このパスに、実際に存在するHTMLファイルのフルパスをパラメータとして与え、 CreateProcess でインターネットエクスプローラを起動する。 ちなみに、この作業をしている実行プログラムと上記のHTMLファイルは 同じディレクトリ上に存在する。 CreateProcess の lpCurrentDirectory にNULLを与えれば、 「新しいプロセスのカレントドライブとカレントディレクトリは、 呼び出し側プロセスと等しくなります」との説明がある。


  • 指定した、HTMLファイルの中に、img Src="hoge.jpg" 等の指定があっても、 この段階ではきちんと読み込まれ、表示される。 ここまでは、他の方法と同じ結果である。


  • 表示されている、インターネットエクスプローラのウインドウハンドルを得 て、 これが CreateProcess されたものと同じ PROCESS_INFORMATION の dwProcessId かどうか確かめる。 同一ならクラス名が EFrame であることを確認し、子ウインドウを検索する。 クラス名が Internet Explorer_Server であるウインドウを見つけ、このウインドウ から IID_IHTMLDocument2 インターフェースを得る。
    かなり強引!


  • この IID_IHTMLDocument2 インターフェース に対して、img Src="hoge.jpg" 等を含む文字列を write する。


  • やはり、この画像のプロパティは、about:blankhoge.jpg となり、 読み込むことが出来ない。
 どうしてもこのジレンマから抜け出すことは出来ない...

 さて、インターネットエクスプローラの内部から write してみたらどうなるのでしょうか。 テストに使ったHTMLファイルの内容は、下です。
<html>
<script language=JavaScript>
function OnClick()
{document.write("<html><body><img src=\"ok.gif\"></body></html>>");}
</script>
<body>
<img src="hoge.gif" onClick="OnClick();">
</body>
</html>


 下はインターネットエクスプローラに表示させた後、画像を左ボタンクリックした状態です。 

 無事に say-ok.jpg が読み込まれています。

 では、「インターネットエクスプローラの不思議 その 2」でもやりましたが、下のスクリプトではどうなるのでしょうか?
var IE = WScript.CreateObject("InternetExplorer.Application");
IE.Visible = true;
IE.Navigate('d:\\WorkSpaceD\\WB2\\Release\\say-ok.html');
while(IE.busy);
while(IE.Document.readyState != 'complete');
IE.Document.write("<html><body><img src=\"ok.gif\"></body></html>");




 最初に、say-ok.html を Navigate で読み込ませたはずなのにタイトルは about:blank になってしまっています。 スクリプトが write する時、about:blank で初期化しているのでしょうか...

 ドラッグアンドドロップやダブルクリックでHTMLファイルが読み込まれた時、インターネットエクスプローラの中でどんなことが起きているのか、少し探ってみました。 テストに使ったHTMLファイルの内容は、下です。
<html>
<body id="body_id">
<img src="hoge.gif" onClick="span_id.innerText = body_id.innerHTML;">
<hr /><span id="span_id"></span>
</body>
</html>


 下はインターネットエクスプローラに表示させた後、画像を左ボタンクリックした状態です。 内部で持っている情報を表示させています。


 読み込ませたソースと微妙に違うので、インターネットエクスプローラの内部で解釈された結果と推測されます。 ここでは、img src="hoge.gif" は展開されていません。 しかし、画像を右ボタンクリックしてプロパティを見てみると、file:/// プロトコルと解釈されています。

 この状態は、ローカルのハードディスクに置かれたHTMLファイルを読み込み、プログラムから body の内容を書き換えた時と動作は同じです。

 ファイルをインターネットエクスプローラにドロップする動作で、プログラムから Document.write した場合と同じ動きをする条件を探ってみた。
  • xsl 文書の拡張子を html にする

  •  何も表示されない。 ソースをみると全部ある。 これが同一。
  • xml 文書の拡張子を html にする

  •  xml 宣言以下の、タグを外した内容のみが表示される。 これも同一。
  • 拡張子を txt にする

  •  内容がそのまま表示される
 xml 系の文書に関しては、インタネットエクスプローラは、ファイルの拡張子から、自分が xml 文書を開くのだということを知っているようだ。 多分、3文字分、xml と xsl のようだ。 例えば、 xmlabc とかにしても、xml 文書として処理する。 プログラムから xml 文書を Document.write した場合は、インターネットエクスプローラは、単純に html 文書として扱っているようだ。 これが問題なんだなぁ...

 IWebBrowser2 インターフェース に RegisterAsDropTarget というプロパティがあり、気になっていたのですが、これについての解説が、(Sets or retrieves a value that indicates whether the is registered as a drop target for navigation.)ということで、意味をつかめません。  とりあえず、これを FALSE にすると、一回のドロップは受け付けますが、二回目からは拒否されます(進入禁止マーク?になる)
 ますます、深みにはまり込んでしまうのでしょうか...

 インターネットエクスプローラは、XMLファイルを読み込んだ時、階層表示をしてくれるとても便利な機能がある。 XMLファイルをダブルクリックするか、ドラッグアンドドロップすると、下の画像のような表示をしてくれる。

 これも、内容を Document.write しただけでは、内容をまったく評価してくれない。 右ボタンクリックの「ソースを表示」を選択すると、書き込んだXML文書の中身が見えるだけである。

 いろいろなことから、インターネットエクスプローラは、自分がいま何をしようとしているのか認識しているように思える。 同じようにプログラムからインターネットエクスプローラに指示を出す方法は無いものか?

 説明は、スクリプトを使ったが、実際は、IID_IWebBrowser2 や IID_IHTMLDocument2 インターフェースを使って、C++ で直書きしている。 せめてプログラムからインターネットエクスプローラにHTMLやXMLファイルをドロップする方法は無いものか?

 こんなことは「じょーしき」で、悩むのは、この年老いたこのじじい...「ウエルテルと呼んで!」だけなのか? 誰か、教えて下さい。

07/27/2004 8:22 AM

おはようございます。 Cafe of Wilderness 開設 Wunderfull !!!
いきなりすごい記事です。普段は、こんな見方したこと無いです。
IEは、ノードをちゃんと階層構造として表示しているのですね。
IEを逆アセンブルして、うううおそろしや、おそろしや。
WinFxも勉強しなくては、

スー

07/27/2004 9:59 AM

 スーさん、おはようございます。 インターネットエクスプローラは使わない! という人もいらっしゃるので、いじりまわしても意味がないのかもしれませんが、気持ちに引っかかってしまったので、もう解明するしか自分を救う方法がないのです。(にが...笑)

本人

 スクリプトで、body 部分に書き込む。
var IE = WScript.CreateObject("InternetExplorer.Application");
IE.Visible = true;
IE.Navigate('about:blank');
while(IE.busy);
while(IE.Document.readyState != 'complete');
IE.Document.body.innerHTML = "<b>hoge</b><br><img src=hoge.gif>";
 上記は、about:blankhoge.gif タイプで失敗する。
 しかし、下記のように実際に存在するHTMLファイルを読み込んだ後、body を書き換えるケースでは、無事に file:///.... タイプに変換され希望の動作となる。
IE.Navigate('f:\\directory\\a.htm');
これでは、テンプレートとなるファイルが先に存在していなければならないために、HTML文書をファイルに書き出し、それを IE.Navigate する方がスマートである。

 とにかくプログラマのわがままとして、バッチファイルを作ったり、テンポラリファイルに書き出したり、そんなことをしないで、プラグラム上から思いどおり操作したい!

 単純なHTMLファイル、をダブルクリックしてみる。 ファイルをドラッグアンドドロップしても結果は同じ。 内容は...
<html><head><title>hoge</title></head>
  <body><b>hoge</b><br><img src=hoge.gif></body></html>
img src=hoge.gif は下の画像のように変換される。


 今度はスクリプトでHTMLの内容を全部書き換えてみる。 スクリプトの内容は...
var IE = WScript.CreateObject("InternetExplorer.Application");
IE.Visible = true;
IE.Navigate('about:blank');
while(IE.busy);
while(IE.Document.readyState != 'complete');
IE.Document.write("<html><head><title>hoge</title></head>
  <body><b>hoge</b><br><img src=hoge.gif></body></html>");
結果、表示されるのは...。

  この about:blankhoge.gif って?
初期化が、about:blank で行われるのが原因かも? と思い既存のHTMLファイルを読み込んでから Document.write しても結果は同じである。

 同じソースコードなのに、内部での処理が違う。

 いま、煮詰まっている「インターネットエクスプローラの不思議」については、徐々に纏めて行こうと思っていますが、 まず始めに。 HTML ファイルをインターネットエクスプローラにドラッグしたらどうなると思いますか?
 ショートカット作成ポインタ になります。
 では、ショートカットやインターネット ショートカットをドラッグしたら? 同じように、ショートカット作成ポインタになります。
 ツールバーの「お気に入り」にドラッグすると、?
 コピーアイコンになります。
 さて、ショートカットを「メモ帳」などの太古のアプリケーションにドラッグすると、ばけばけ文字が表示されます。 他の多くのソフトウエアは、ショートカットをリンクされたファイルと同じように扱います。

 さて、ここで問題。 プログラムでインターネットエクスプローラに、WM_DROPFILES をポストし、ファイルのドロップと同じことをしてみました。 結果、ファイルをドロップした時、コピーポインタになるソフトウエアでは、希望する動作になりました。 でも、インターネットエクスプローラでは、メッセージを受け取っているにも関わらず(Spyで確認)何事も起こりません。 試しに、ショートカット(lnk)、インターネットショートカット(url) を指定して、WM_DROPFILES してみましたが、希望する動作になりません。 エクスプローラとインターネットエクスプローラとの組み合わせでは、仲良くやっているのに...プログラムからこの動作をさせる方法はないの?

07/27/2004 10:19 AM

 追記です。 同じ形態のアイコンでも、「ショートカット」と「インターネット ショートカット」は違うようです。 「ショートカット」は隠された拡張子が、 lnk 「インターネット ショートカット」は、url です。 「インターネット ショートカット」はテキストベースに進化し、メモ帳でも読み書き出来ます。 別にURLでなくても、ローカルのファイルなどを書いておけば、動作します。 使いようによっては便利なのだろうと思います。
 拡張子が隠されているので、一見同じ名前のファイルが3つ同じディレクトリに存在しているように勘違いしてしまいます。

本人