none
IE8で、ウィンドウを前に表示させる方法はありませんか RRS feed

回答

  • 確認環境を増やしました。同じIE8でも3パターンに分かれました。

    focusが失敗とは、タスクバーに入っているプロセスが黄色く点滅する状態のことを指しています。
    focusが成功とは、ウィンドウが前面になることを指しています。

    マシン1:IE8+XP3(デスクトップ,Core2Duo 2.6G)
               →focusが成功したり失敗したりする。
    マシン2:IE8+XP2(デスクトップ,Pen4 Dual 2.0G)
               →focusが成功したり失敗したりする。
                成功確率はマシン1より20%程低い。
    マシン3:IE8+XP3(ノートPC,Atom1.6G)
               →focusが成功したことはない。
    マシン4:IE8+XP3(VMWare)    →focusが失敗したことはない。
    マシン5:IE8+Win7RC(VMWare) →focusが失敗したことはない。

    マシン1とマシン2における、focusの成功タイミングに連続性や状況に応じて、発生の有無が
    大きく変わるという事態は発生していません。ほぼランダムに発生しています。
    マシン3における試行回数は1000回ぐらいです。同じHTMLファイルです。
    インターネットゾーンかつ、ドメイン配下ではなく、プロトコルはHTTPです。(マシン2のみドメイン配下)

    レジストリTabProcGrowthを設定する(LCIEをOFFにする)ことで、
    focusが必ず成功するようになりました。(マシン1,2,3全てで必ず成功するようになる)
    http://social.technet.microsoft.com/Forums/ja-JP/internetexplorerja/thread/3c65fcfe-43ed-4ea5-8cf5-8adb50ddc508
    JSで実現できなければ、最悪この方法ですかね(LCIEのメリットもなくなりますが)。

    また、Windowをフォアグラウンドにする条件は以下にありました。
    http://msdn.microsoft.com/ja-jp/library/cc411039.aspx

    話題にしていた、IE8でfocusを効かないようにした理由については、
    LCIEのせいで、上記条件を満たせなくなることが発生するようになったからだと思いました。

    >下記のようにソースを修正して、テストしましたが、前面になってくれませんでした。
    こちらが動いたソースはまさにそれです。
    マシン1と2では全面になりましましたが、マシン3ではこちらも前面になってくれませんでした。

    ■■同じIE8でも動作が3パターンに分かれているように見える理由は何か?
    LCIEの"ルーズさ"が原因と言い切っていいのか。
    マシン1、2は開発機としてデバッグ用にIEのプラグインやツールを多数インストールしています。
    マシン3は、東芝NB100で、買った直後(数か月放置したままでしたが)のものに、IE8をインストールしたものです。
    なんとなく、マシンスペックやメモリなどのハードウェアに応じて動作が分かれているように思えました。
    hatzhangさんのマシンスペックってどんな感じですかね?

    ■■マシン1、2でfocusが成功したり失敗したりする原因について
    フォアグラウンドロックタイムアウトに引っ掛かったと考え、以下のコマンドプログラムを作りましたが、
    0しか返却されませんでした。
    int main(int argc, char *argv[]) {
     DWORD svTmOut;
     for( ;; ) {
      ::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, (void *)&svTmOut, 0);
      printf("TmOut[%d]\n", svTmOut);
      ::Sleep(50);
     }
     return 0;
    }
    SystemParametersInfoの前後にAttachThreadInputを入れても同じ結果でした。

    • 回答としてマーク hatzhang 2009年8月19日 10:48
    2009年8月15日 7:24
  • .focus()だけでは難しいですね。外部オブジェクトを使えば、ここまで出来ますが、
    http://scripting.cocolog-nifty.com/blog/2009/08/ie7ie8windowope.html

    そこまでやります?
    • 回答としてマーク hatzhang 2009年8月19日 10:48
    2009年8月15日 10:23
  • ※2スクバーに入っているプロセスが黄色く点滅する状態から開くと、「メッセージ: ';' がありません。」のエラーが表示されます。
    javascriptで解釈されていますね。
    win.setTimeout "MsgBox ""focus moving..."",vbSystemModal",0,"vbscript"
    と明示してやっても駄目なようで、デフォルトlanguageで解釈されるようです。(変な仕様?) ← 勘違い
    child.htmの最初のスクリプトブロックをvbscriptにしてみてください。 → 明示すればOK
    マシンで変わるのが不思議ですが。

    マシン7の方法3では、MsgBoxがちゃんと出てます?

    ※3方法1で、一旦成功したら、こちらも連続成功します。
    一度AppAcivateすると、なぜかfocusが効くようになりますね。

    マシン6の方法2は、子ウィンドウのタイトルバーを確認してください。タイトルが表示されてます?
    なぜか、URLのままのことがあるんです。

    よく詳しくないですが、方法1と2は、タブ以外の差分もあるように見受けられます。
    方法1では、タイトルでAppActivateして駄目ならURLでAppActivateしてるので、そのせいかも。

    マシン6では、focusは成功しません。マシン7では、50%成功します。

    マシンのスペックより、動きが変わるのは、IEのバッグと言えばいいでしょうか。
    同じマシンでも、私の場合、
    ieを先に1つ開いて、別に親を開くと、子にfocusが効く。
    親だけ開くと、子にfocusが効かない。
    となります。なぜなのか、さっぱり分かりません。
    2009年8月17日 10:43
  • >マシンのスペックより、動きが変わるのは、IEのバッグと言えばいいでしょうか。

    スペックというより、当方で発生していた事象と同じで、フォアグラウンドタイムアウト値が異なるのが原因だと思われます。
    マシン6は、タイマ値が200000で、
    マシン7はタイマ値が0になっているのだと思いました。

    結局マシン2もタイマ値0だったので。
    おそらくマウスを触った時間と判定タイミングがms単位で一致しちゃうかどうかという微妙な所でfocusが成功する・しないが変ると。
    前はびっくり度合いと表現しましたが、結局の所、ボタン押下後に経過した時間によって成功の有無が変わるんでしょうね。
    VMWareで必ずfocusが成功しているのは、仮のデバイスだから、色々嘘情報になっちゃっているからでしょう。たぶん。

    参考程度に、フォアグラウンドロックタイマは、Excelが入っていれば、以下をブラウザのURL欄に投入しても変更可能ではあります。
    別途事前に値を確認しておくのをお勧めしますが。
    (警告がいくつか出ます。ウィンドウズスクリプトプログラマさんのサイトを見るとこんな方法があることを知った)

    【タイマー値0  =単なる.focus()が効いたり効かなかったりするようになる =使い倒したマシンはえてしてこちらのケースになる】
    javascript:alert( (new ActiveXObject("Excel.Application")).ExecuteExcel4Macro('CALL("user32","SystemParametersInfoA","JJJJJ",8193,0,0,0)')?"設定完了!":"" )

    【タイマー値200000 =単なる.focus()は効かない=OSインストール直後の状態】
    javascript:alert( (new ActiveXObject("Excel.Application")).ExecuteExcel4Macro('CALL("user32","SystemParametersInfoA","JJJJJ",8193,0,200000,0)')?"設定完了!":"" )
    • 回答としてマーク hatzhang 2009年8月19日 10:55
    2009年8月17日 18:43
  • さらに調査を進めました。

    【調査で判明したこと】
    ※マシン1などの表記は前レスと同じです。

    マシン1はフォアグラウンドロックタイムアウト値は0でしたが、
    マシン3,4,5はフォアグラウンドロックタイムアウト値は200000(単位ms)でした。
    マシン1でフォアグラウンドロックタイムアウト値を200000にすると、focusは成功しなくなりました。

    フォアグラウンドロックタイムアウト値が0であれば、
    フォアグラウンドでないプロセスがSetForegroundWindowを発行しても成功する。
    フォアグラウンドロックタイムアウト値が200000で、タイムアウトしていない場合、
    フォアグラウンドでないプロセスがSetForegroundWindowを発行すると失敗する。

    【提案出来る対応案】
    3つ増えました。全部ヘボです。

    案1:実行マシンにおけるフォアグラウンドロックタイムアウトを0にし、
       HTMLでは、window.open("javascript:void(0)", "x")してから.focus()する。
       対象が特定グループ内だと、LCIEをOFFにするより良いかもしれないです。

    案2:
    フォアグラウンドロックタイムアウト値のデフォルトは200000msのようです。
    (マウスも動かさずに←最重要!)200秒後にfocusを呼べば前面になります。3回試して、3回とも成功しました。
      ⊥_⊥
     ( ・∀・) そのままマウスとキーボードを触らず、4分ほどお待ちください。
     ( つ  つ

    …すみません。

    案3:ウィンドウが2つしかない前提であれば、
       呼び出し元Windowで.blur()すると、もう片方が全面になったように見える。
       (blur()の動作が最奥に行くのではなく、1つ奥に行くという動作であれば、もっとよかったんですが。。)

    【考察】
    http://msdn.microsoft.com/ja-jp/library/cc411039.aspx または、英語だと
    >A process can set the foreground window only if one of the following conditions is true:
     ↑これは1つでもtrueなら成功するって言ってます?
    の記載は、And条件なのかOr条件なのかが良く分からなかったのですが、混在しているんですね。
    出来れば、どなたかフロー形式に直すと迷わなくすむかも。

    マシン1がフォアグラウンドロックタイムアウト値が0になっている理由について、
    勝手アプリの場合、フォアグラウンドロックタイムアウトのような全プロセス共有のデータを
    ロックもせずに一時的に0に書き換えている手法が当たり前のように出回っている現状を考えると、
    様々なプログラムを長く使っているマシンほど、値が0になっている可能性が高そうだと思いました。
    (まぁ戻し忘れているプログラムがあったと考えた方がよさそうですが)
    というより英語版のMSDNを見てみるとそもそも元に戻すこと自体がフォアグラウンドウィンドウしか出来ないと
    書いてあって、他ウィンドウをSetForegroundWindowした後に、成功するかは結構怪しいですね。(試すと成功しますが)

    MSはそれはよくないと考え、しなかったんでしょう(その制限の考案者ですし)。

    【その他】
    >ウィンドウズスクリプトプログラマさん
    こちらは「常に新しいウィンドウでポップアップを開く」の話でした。
    タブの場合、SendKeyでCTRL+TABコード送信によって、ウィンドウを前面にするという手だと認識しました。


    個人的には、JavaScriptでwindow.focus()を呼ぶ直前に、なんとか
    ・フォアグラウンドウィンドウをなくさせる方法
    ・window.openの起動元であるLCIEの管理用プロセス?にフォーカスを当てる方法
    が見つかれば、focus()が効きそうだと思ってるのですが、なさそうですね。

    • 回答としてマーク hatzhang 2009年8月19日 11:08
    2009年8月15日 13:13

すべての返信

  • こちらの KB で紹介されている方法はいかがでしょう。

    ショートカットファイル (*.url) から Internet Explorer を起動するとウィンドウが最前面に表示されない
    http://support.microsoft.com/kb/893393/ja

    hebikuzure
    2009年8月11日 13:05
    モデレータ
  • 質問の前提として、サーバサイド(+クライアントスクリプト)の開発をしていて、
    新たなActiveXプラグインなどのインストールはしないということでよいでしょうか?
    なのでレジストリやセキュリティ設定はいじれない前提と考えています。

    実現したいことはshowModalDialogやshowModelessDialogでは実現出来ないということで良いですかね?

    それ以外に思いついた案は、「ウィンドウを閉じて、再度開く」しかありませんでした。

    以下の案を考えましたが、全てダメでした。
    ・EmulateIE7だとfocus()が保証されるかも?
      →X-UA-Compatibleの値によらず、focus警告が出るという動作となりました。
    ・リフレッシュさせたり、フルスクリーンにしてみると、動作が変わるかも!?
      →ダメそうなので試してない。
    ・document.execCommand("print",true);
      →前面にならず。プリンタダイアログは、前面になるイメージだったので。alertと違って、ツールバーが点滅しないんですね。
    ・FlashやSilverLightのsetFocus()
      →机上調査しただけですが、ウィンドウのZオーダーは変更することは出来ないようですね。

    しかし、focus()でウィンドウが前面にならないのであれば、
    setActive(DOMActivate)との違いが少なくなりますね(バブルの有無は別にして)。
    一応、ツールバーが点滅するので、注目はしてくれると思いますが。

    hatzhangさんが以下でも質問中なので、メモがてらリンクしておきます。
    http://social.microsoft.com/Forums/en-US/iewebdevelopment/thread/a250c431-9f09-441c-9b78-af067233ed78

    Hebikuzureさんが書かれたサイトって対象がIE6とIE6SP1のようですが、
    昔の記事の場合、以降のブラウザにも引き継がれている場合はあるんですか?

    2009年8月11日 16:37
  • 返事ありがとうございます。
    実現したいシーンは下記の質問と同じく、簡単です。
    (メインウィンドとメインウィンドから開いた子ウィンドがあって、メインウィンドの何か操作で、子ウィンドを最前面に表示する)

    Hebikuzureさんから提示した方法はちょっと別シーンだと思いますが...

    前提といえば、
    例えば、javascriptで実現できない場合、
    ActiveXプラグインなどの利用、
    又は、レジストリやセキュリティ設定の変更によって、
    これを実現することは可能でしょうか。

    2009年8月12日 5:31
  • hatzhang さんの質問の趣旨がうまくくみ取れず失礼しました。
    別のウィンドウのフォーカスを制御できなくなったのは、おそらくセキュリティ的な意味合いでしょう。

    (´・ω・`) さん
    古い製品が対象の技術情報ですが、事例や経験からすると単に更新されていないだけで新しい製品でも同様な物も少なくないですが、新しい製品では修正/変更されている場合もありますね。
    今回は制御するレジストリが IE の動作ではなく Windows 全体の動作を設定する物なので、IE のバージョンに関係なく機能すると思います。

    hebikuzure
    2009年8月12日 13:20
    モデレータ
  • む、こちらでは、リンク先で出ているものでうまくいきますね。

    win = window.open('FocusExample_Window2.html','mywin','width=200,height=200')
    win.focus();
    focus()を単体で呼び出すのではなく、一旦window.openを(第2引数は変えないようにして)呼び出した後にfocusを呼ぶと、
    focusが動作するようですね。(タイマーイベント中でもこの方法で動きました)

    しかし、hatzhangさんが懸念している問題は未決のままですね。

    こうなってくると、そもそもIE8でfocusを動作させないようにした理由は、
    どういう問題を防ぎたかったんでしたっけ(色々と問題になりやすい、という答えかもしれませんが)。
    上記のコードで行く場合は、「セキュリティ的な意味合い」をはっきり把握する必要があるかもです。
    2009年8月12日 13:31
  • 「セキュリティ的な意味合いで」という推測が正しければ、どういう理由なのかという事について具体的な例が Microsoft から示される事はないと思います (悪用の手口を示す事になるので)。
    ごく大雑把に言えばユーザーをミスリードするのに利用できる...というような事ではないかと思いますが。

    hebikuzure
    2009年8月13日 14:07
    モデレータ
  • >hatzhangさん
    >実際の検証で、focusが動作する場合もありますが、
    この点について、調査をしました。


    method\Browser IE8+XP SP3 IE8+Win7 Safari4.0.2 FireFox3.5.2
    focus only 56/600 100/100 150/150 100/100
    window.navigate&
    javascript:void(0)
    97/600 100/100 no support no support
    location.href &
    javascript:void(0)
    312/600 100/100 100/100 100/100
    window.open &
    javascript:void(0)
    100/100 100/100 100/100 100/100


    表の見方は、
    「ウィンドウが前面になった回数/試行回数」で、
    ウィンドウが前面になった回数の算出方法は、window.onfocusイベントが発生した回数を見ていますが、
    それが一致することは目視にて確認しております。

    IE8+XP SP3の環境で2台試して2台とも、同じような確率で発生しています。
    ただし、window.openの方法は、片方のマシンでは90%程度の確率でしかウィンドウが前面になりませんでした。
    Chromeはウィンドウは前面になってくれませんでした。(window.onfocusは発生するにもかかわらず)

    上記結果から、focusを成功させるにはIEをビックリさせる度合いが重要だと思いました。
    手元のマシンだけでなく、他マシンでも同様の再現率であれば、
    ループで120回ほどfocusを連続で呼ぶだけでも、99.9%以上の確率で成功します。

    長いですが、試したコードを貼り付けておきます。

    <!DOCTYPE html
       PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html>
    <head>
    <script language="javascript" type="text/javascript">
    var win;
    function windowFocus()
    {
    	win = window.open('FocusExample_Window2.html','mywin','width=200,height=200')
    }
    
    var numFocusNum = 0;
    function numFocus(){
    	numFocusNum++;
    	win.focus();
    	numOutput();
    }
    
    var navi_void0Num = 0;
    function navi_void0(){
    	win.navigate("javascript:void(0)");
    	win.focus();
    	navi_void0Num++;
    	numOutput();
    }
    
    var href_void0Num = 0;
    function href_void0(){
    	win.location.href = "javascript:void(0)";
    	win.focus();
    	href_void0Num++;
    	numOutput();
    }
    
    var Open_void0Num = 0;
    function Open_void0(){
    	win = window.open('javascript:void(0)','mywin');
    	win.focus();
    	Open_void0Num++;
    	numOutput();
    }
    
    function numOutput(){
    	var str = [];
    	str.push("Focus only:" + numFocusNum);
    	str.push("NAVIvoid0:" + navi_void0Num);
    	str.push("HREFvoid0:" + href_void0Num);
    	str.push("OPENvoid0:" + Open_void0Num);
    	document.getElementById("out").innerHTML = str.join("<br>");
    }
    </script>
    </head>
    <body>
    	<a href="" onclick="windowFocus(); return false;">Open the Window</a>
    	<br><br>
    	<a href="" onclick="numFocus(); return false;">Focus only</a>
    	<br><br>
    	<a href="" onclick="navi_void0(); return false;">window.navigate&javascript:void(0)</a>
    	<br><br>
    	<a href="" onclick="href_void0(); return false;">location_href&javascript:void(0)</a>
    	<br><br>
    	<a href="" onclick="Open_void0(); return false;">window.open&javascript:void(0)</a>
    <hr>
    <span id=out></span>
    </body>
    </html>
    



    >Hebikuzureさん
    >「セキュリティ的な意味合いで」という推測が正しければ
    たしかに、http://msdn.microsoft.com/ja-jp/library/ms536425(en-us,VS.85).aspxでは、
    IE7はセキュリティの理由でと書いてありますが、IE8については理由が書かれていませんね。

    2009年8月13日 15:03
  • (´・ω・`) さん、Hebikuzureさん : ありがとうございます。

    >セキュリティ的な意味合いで
    セキュリティ上の考えであれば、インターネット、ローカルイントラネットなどのゾーン毎に、
    カスタマイズできるようにするべきだと思います。
    これを実現できないと、ユーザエクスペリエンスが変わってしまう。


    >focusを成功させるにはIEをビックリさせる度合いが重要
    とても抽象ですね (笑)

    (´・ω・`) さんのサンプル、私も試してみました。
    結果は、XPsp3、IE8で、何回やっても、成功できませんでした。
    特に、
    >ループで120回ほどfocusを連続で呼ぶ
    に対し、下記のようにソースを修正して、テストしましたが、前面になってくれませんでした。
    function numFocus(){
    	for(var i=0; i<200 ; i++) {
    		numFocusNum++;
    		win.focus();
    		numOutput();
    	}
    }

    >実際の検証で、focusが動作する場合もあります
    これは(可笑しいと思いますが)、
    ある特定期間※、focusは何回やっても成功しますが、それ以外の時間帯では、全部成功しません。
    また、複雑なフレーム関係を持つ画面は、偶に成功する場合もあります。
    ※(一回だけです)
     sp3を削除直後
     sp3をインストールした翌日の午前

    これは安定の方法ではないと思いますので、特に再現試験などを行いませんでした。









    2009年8月14日 15:33
  • 確認環境を増やしました。同じIE8でも3パターンに分かれました。

    focusが失敗とは、タスクバーに入っているプロセスが黄色く点滅する状態のことを指しています。
    focusが成功とは、ウィンドウが前面になることを指しています。

    マシン1:IE8+XP3(デスクトップ,Core2Duo 2.6G)
               →focusが成功したり失敗したりする。
    マシン2:IE8+XP2(デスクトップ,Pen4 Dual 2.0G)
               →focusが成功したり失敗したりする。
                成功確率はマシン1より20%程低い。
    マシン3:IE8+XP3(ノートPC,Atom1.6G)
               →focusが成功したことはない。
    マシン4:IE8+XP3(VMWare)    →focusが失敗したことはない。
    マシン5:IE8+Win7RC(VMWare) →focusが失敗したことはない。

    マシン1とマシン2における、focusの成功タイミングに連続性や状況に応じて、発生の有無が
    大きく変わるという事態は発生していません。ほぼランダムに発生しています。
    マシン3における試行回数は1000回ぐらいです。同じHTMLファイルです。
    インターネットゾーンかつ、ドメイン配下ではなく、プロトコルはHTTPです。(マシン2のみドメイン配下)

    レジストリTabProcGrowthを設定する(LCIEをOFFにする)ことで、
    focusが必ず成功するようになりました。(マシン1,2,3全てで必ず成功するようになる)
    http://social.technet.microsoft.com/Forums/ja-JP/internetexplorerja/thread/3c65fcfe-43ed-4ea5-8cf5-8adb50ddc508
    JSで実現できなければ、最悪この方法ですかね(LCIEのメリットもなくなりますが)。

    また、Windowをフォアグラウンドにする条件は以下にありました。
    http://msdn.microsoft.com/ja-jp/library/cc411039.aspx

    話題にしていた、IE8でfocusを効かないようにした理由については、
    LCIEのせいで、上記条件を満たせなくなることが発生するようになったからだと思いました。

    >下記のようにソースを修正して、テストしましたが、前面になってくれませんでした。
    こちらが動いたソースはまさにそれです。
    マシン1と2では全面になりましましたが、マシン3ではこちらも前面になってくれませんでした。

    ■■同じIE8でも動作が3パターンに分かれているように見える理由は何か?
    LCIEの"ルーズさ"が原因と言い切っていいのか。
    マシン1、2は開発機としてデバッグ用にIEのプラグインやツールを多数インストールしています。
    マシン3は、東芝NB100で、買った直後(数か月放置したままでしたが)のものに、IE8をインストールしたものです。
    なんとなく、マシンスペックやメモリなどのハードウェアに応じて動作が分かれているように思えました。
    hatzhangさんのマシンスペックってどんな感じですかね?

    ■■マシン1、2でfocusが成功したり失敗したりする原因について
    フォアグラウンドロックタイムアウトに引っ掛かったと考え、以下のコマンドプログラムを作りましたが、
    0しか返却されませんでした。
    int main(int argc, char *argv[]) {
     DWORD svTmOut;
     for( ;; ) {
      ::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, (void *)&svTmOut, 0);
      printf("TmOut[%d]\n", svTmOut);
      ::Sleep(50);
     }
     return 0;
    }
    SystemParametersInfoの前後にAttachThreadInputを入れても同じ結果でした。

    • 回答としてマーク hatzhang 2009年8月19日 10:48
    2009年8月15日 7:24
  • .focus()だけでは難しいですね。外部オブジェクトを使えば、ここまで出来ますが、
    http://scripting.cocolog-nifty.com/blog/2009/08/ie7ie8windowope.html

    そこまでやります?
    • 回答としてマーク hatzhang 2009年8月19日 10:48
    2009年8月15日 10:23
  • さらに調査を進めました。

    【調査で判明したこと】
    ※マシン1などの表記は前レスと同じです。

    マシン1はフォアグラウンドロックタイムアウト値は0でしたが、
    マシン3,4,5はフォアグラウンドロックタイムアウト値は200000(単位ms)でした。
    マシン1でフォアグラウンドロックタイムアウト値を200000にすると、focusは成功しなくなりました。

    フォアグラウンドロックタイムアウト値が0であれば、
    フォアグラウンドでないプロセスがSetForegroundWindowを発行しても成功する。
    フォアグラウンドロックタイムアウト値が200000で、タイムアウトしていない場合、
    フォアグラウンドでないプロセスがSetForegroundWindowを発行すると失敗する。

    【提案出来る対応案】
    3つ増えました。全部ヘボです。

    案1:実行マシンにおけるフォアグラウンドロックタイムアウトを0にし、
       HTMLでは、window.open("javascript:void(0)", "x")してから.focus()する。
       対象が特定グループ内だと、LCIEをOFFにするより良いかもしれないです。

    案2:
    フォアグラウンドロックタイムアウト値のデフォルトは200000msのようです。
    (マウスも動かさずに←最重要!)200秒後にfocusを呼べば前面になります。3回試して、3回とも成功しました。
      ⊥_⊥
     ( ・∀・) そのままマウスとキーボードを触らず、4分ほどお待ちください。
     ( つ  つ

    …すみません。

    案3:ウィンドウが2つしかない前提であれば、
       呼び出し元Windowで.blur()すると、もう片方が全面になったように見える。
       (blur()の動作が最奥に行くのではなく、1つ奥に行くという動作であれば、もっとよかったんですが。。)

    【考察】
    http://msdn.microsoft.com/ja-jp/library/cc411039.aspx または、英語だと
    >A process can set the foreground window only if one of the following conditions is true:
     ↑これは1つでもtrueなら成功するって言ってます?
    の記載は、And条件なのかOr条件なのかが良く分からなかったのですが、混在しているんですね。
    出来れば、どなたかフロー形式に直すと迷わなくすむかも。

    マシン1がフォアグラウンドロックタイムアウト値が0になっている理由について、
    勝手アプリの場合、フォアグラウンドロックタイムアウトのような全プロセス共有のデータを
    ロックもせずに一時的に0に書き換えている手法が当たり前のように出回っている現状を考えると、
    様々なプログラムを長く使っているマシンほど、値が0になっている可能性が高そうだと思いました。
    (まぁ戻し忘れているプログラムがあったと考えた方がよさそうですが)
    というより英語版のMSDNを見てみるとそもそも元に戻すこと自体がフォアグラウンドウィンドウしか出来ないと
    書いてあって、他ウィンドウをSetForegroundWindowした後に、成功するかは結構怪しいですね。(試すと成功しますが)

    MSはそれはよくないと考え、しなかったんでしょう(その制限の考案者ですし)。

    【その他】
    >ウィンドウズスクリプトプログラマさん
    こちらは「常に新しいウィンドウでポップアップを開く」の話でした。
    タブの場合、SendKeyでCTRL+TABコード送信によって、ウィンドウを前面にするという手だと認識しました。


    個人的には、JavaScriptでwindow.focus()を呼ぶ直前に、なんとか
    ・フォアグラウンドウィンドウをなくさせる方法
    ・window.openの起動元であるLCIEの管理用プロセス?にフォーカスを当てる方法
    が見つかれば、focus()が効きそうだと思ってるのですが、なさそうですね。

    • 回答としてマーク hatzhang 2009年8月19日 11:08
    2009年8月15日 13:13
  • もし、複数タブを考えなくてよいなら、簡単です。
    CreateObject("WScript.Shell").AppActivate(win.document.title)

    2009年8月16日 6:49
  • うーん。原文をもう少し検証してみますか。

    Windows Internet Explorer 8 and later. The focus method no longer brings child windows (such as those created with the open method) to the foreground. Child windows now request focus from the user, usually by flashing the title bar. To directly bring the window to the foreground, add script to the child window that calls the focus method of its window object.

    userってのはIEを触っているユーザのことですよね。
    usuallyを付けている理由は、上記までに出てきた条件などがあるからでしょうね。
    最後の文は、子ウィンドウのWindowオブジェクトであれば、手前に持ってこれるよ。って書いてあるように見えるのですが、
    win.window.focus()とやっても、やっぱりダメですねぇ。

    自発的に手前になろうとするのか、人に言われて手前になろうとするかによって動作が異なる可能性があると思ったんですが。

    2009年8月16日 16:57
  • ユーザ設定も変えず、外部オブジェクトも使わないでやろうとすると、これがベストかな

    Sub MsgActivate(win)
    win.focus
    win.document.focus
    If win.document.hasFocus() Then Exit Sub
    win.setTimeout "MsgBox ""focus moving..."",vbSystemModal",0,"vbscript"
    End Sub

    2009年8月17日 7:46
  • ありがとうございます。

    こちらのマシンスペックは下記の通りです。

    マシン6: IE8+XP3(ノートPC,AMD Turion(tm) 64*2 1.79G) 
    マシン7: IE8+XP3(ノートPC,Intel Celeron M 1.50Ghz) 

    マシン6では、focusは成功しません。マシン7では、50%成功します。

    マシンのスペックより、動きが変わるのは、IEのバッグと言えばいいでしょうか。

    また、マシン6では、LCIEの無効化(TabProcGrowth=1)に関するテストを行いました、確かに、100%成功します。
    (フォアグラウンドロックタイムアウトについてはまだ理解中です)

    ウィンドウズスクリプトプログラマさんが提示した下記の方法もやってみました。
    方法1(複数タブを考えて):

    方法2(複数タブを考えなくて):Sub Activate

    方法3(外部オブジェクトも使わない):Sub MsgActivate

    成功率(※1)の結果は下記通りでした。
    window.focus 方法1 方法2 方法3
    マシン6:  0%(※3)      100% 0%(※3) 0%(※2)
    マシン7:  60% 100% 90% 90%

    ※1手動テストで目視に確認、厳密ではありません
    ※2スクバーに入っているプロセスが黄色く点滅する状態から開くと、「メッセージ: ';' がありません。」のエラーが表示されます。
    ※3方法1で、一旦成功したら、こちらも連続成功します。

    よく詳しくないですが、方法1と2は、タブ以外の差分もあるように見受けられます。

    方法2、3のソースは下記の通りです。
    <html>
    <head>
    <title>opener</title>
    <object id=ShellWindows classid=clsid:9BA05972-F6A8-11CF-A442-00A0C90A8F39></object>
    <object id=wShell classid=clsid:72C24DD5-D70A-438B-8A42-98424B88AFB8></object>
    <script language=vbscript>
    Option Explicit
    Dim win
    Sub Activate
    win.focus
    If win.document.hasFocus() Then Exit Sub
    CreateObject("WScript.Shell").AppActivate(win.document.title)
    End Sub
    Sub MsgActivate
    win.focus
    win.document.focus
    If win.document.hasFocus() Then Exit Sub
    win.setTimeout "MsgBox ""focus moving..."",vbSystemModal"
    End Sub
    </script>
    </head>
    <body>
    <button onclick='Set win=window.open("child.htm","_blank","resizable=false")'>open child.htm in window</button>
    <button onclick="win.focus">win.focus</button>
    <button onclick="win.document.focus">win.document.focus</button>
    <button onclick="Activate">Activate</button>
    <button onclick="MsgActivate">MsgActivate</button>
    </body>
    </html>

    • 編集済み hatzhang 2009年8月17日 10:19 change format
    2009年8月17日 9:39
  • ※2スクバーに入っているプロセスが黄色く点滅する状態から開くと、「メッセージ: ';' がありません。」のエラーが表示されます。
    javascriptで解釈されていますね。
    win.setTimeout "MsgBox ""focus moving..."",vbSystemModal",0,"vbscript"
    と明示してやっても駄目なようで、デフォルトlanguageで解釈されるようです。(変な仕様?) ← 勘違い
    child.htmの最初のスクリプトブロックをvbscriptにしてみてください。 → 明示すればOK
    マシンで変わるのが不思議ですが。

    マシン7の方法3では、MsgBoxがちゃんと出てます?

    ※3方法1で、一旦成功したら、こちらも連続成功します。
    一度AppAcivateすると、なぜかfocusが効くようになりますね。

    マシン6の方法2は、子ウィンドウのタイトルバーを確認してください。タイトルが表示されてます?
    なぜか、URLのままのことがあるんです。

    よく詳しくないですが、方法1と2は、タブ以外の差分もあるように見受けられます。
    方法1では、タイトルでAppActivateして駄目ならURLでAppActivateしてるので、そのせいかも。

    マシン6では、focusは成功しません。マシン7では、50%成功します。

    マシンのスペックより、動きが変わるのは、IEのバッグと言えばいいでしょうか。
    同じマシンでも、私の場合、
    ieを先に1つ開いて、別に親を開くと、子にfocusが効く。
    親だけ開くと、子にfocusが効かない。
    となります。なぜなのか、さっぱり分かりません。
    2009年8月17日 10:43
  • >child.htmの最初のスクリプトブロックをvbscriptにしてみてください。
    追加したら、エラーはなくなって、「focus moving...」というメッセージボックスが表示され、「ok」を押下したら、子ウィンドウが表示されました。

    >マシン7の方法3では、MsgBoxがちゃんと出てます?
    出ませんが、「focus moving...」というメッセージボックスも表示されませんでした。

    >マシン6の方法2は、子ウィンドウのタイトルバーを確認してください。タイトルが表示されてます?
    >なぜか、URLのままのことがあるんです。
    その通りです。

    >ieを先に1つ開いて、別に親を開くと、子にfocusが効く。
    >親だけ開くと、子にfocusが効かない。
    マシン6もこれと似ています。
    子ウィンドウを2個開くと、window.focusと方法2が効く場合が多いです。


    2009年8月17日 11:56
  • >マシンのスペックより、動きが変わるのは、IEのバッグと言えばいいでしょうか。

    スペックというより、当方で発生していた事象と同じで、フォアグラウンドタイムアウト値が異なるのが原因だと思われます。
    マシン6は、タイマ値が200000で、
    マシン7はタイマ値が0になっているのだと思いました。

    結局マシン2もタイマ値0だったので。
    おそらくマウスを触った時間と判定タイミングがms単位で一致しちゃうかどうかという微妙な所でfocusが成功する・しないが変ると。
    前はびっくり度合いと表現しましたが、結局の所、ボタン押下後に経過した時間によって成功の有無が変わるんでしょうね。
    VMWareで必ずfocusが成功しているのは、仮のデバイスだから、色々嘘情報になっちゃっているからでしょう。たぶん。

    参考程度に、フォアグラウンドロックタイマは、Excelが入っていれば、以下をブラウザのURL欄に投入しても変更可能ではあります。
    別途事前に値を確認しておくのをお勧めしますが。
    (警告がいくつか出ます。ウィンドウズスクリプトプログラマさんのサイトを見るとこんな方法があることを知った)

    【タイマー値0  =単なる.focus()が効いたり効かなかったりするようになる =使い倒したマシンはえてしてこちらのケースになる】
    javascript:alert( (new ActiveXObject("Excel.Application")).ExecuteExcel4Macro('CALL("user32","SystemParametersInfoA","JJJJJ",8193,0,0,0)')?"設定完了!":"" )

    【タイマー値200000 =単なる.focus()は効かない=OSインストール直後の状態】
    javascript:alert( (new ActiveXObject("Excel.Application")).ExecuteExcel4Macro('CALL("user32","SystemParametersInfoA","JJJJJ",8193,0,200000,0)')?"設定完了!":"" )
    • 回答としてマーク hatzhang 2009年8月19日 10:55
    2009年8月17日 18:43
  • ありがとうございます。

    フォアグラウンドタイムアウト値については試してみました。結果は、(´・ω・`) さんに言いう通り、
    マシン6は、タイマー値が0にしたら、focus()が効いたり効かなかったりするようになりました。

    本件は、ie8のfocus関数の仕様変更より、LCIEのせいで起きるie8のバグだと思いました。
    2009年8月18日 4:12
  • おそらくマウスを触った時間と判定タイミングがms単位で一致しちゃうかどうかという微妙な所でfocusが成功する・しないが変ると。
    そういうことなら、
    setTimeout "win.focus",100

    2009年8月18日 6:54
  • 訳すと
    Windows Internet Explorer 8 およびそれ以降. focus メソッドは子ウィンドウ (open メソッドで作成されたものなど) をフォアグラウンドに持ち上げなくなりました。子ウィンドウは、通常はタイトル バーを点滅して、ユーザーによるフォーカスを要求します。ウィンドウを直接フォアグラウンドに持ち上げるには、それ自身の window オブジェクトの focus メソッドを呼ぶスクリプトを子ウィンドウに追加します。
    などで良いでしょうかね。子ウィンドウ自身のコンテンツとしてスクリプトが記述されていれば、focus できるようですね。

    hebikuzure
    2009年8月18日 11:48
    モデレータ
  • >hatzhangさん

    LCIEのせいで起きるie8のバグだと思いました。
    まぁ、努力する余地はあるはずで、次は直してほしいですね。
    ほとんどのケースで、ユーザにとっても、開発側にとっても手前になって欲しいと思うはずですから。


    >ウィンドウズスクリプトプログラマさん

    setTimeout "win.focus",100
    フォアグラウンドタイマー値が0であれば、その手がよさそうです。
    しかし、ボタンを押した後にマウスを動かし続けていると失敗しますね。何度やっても失敗します。
    最後にマウスを動かしてから0msしかたっていない→タイマーの範囲内→focusは効かないという動作のようです。
    タイマーの判定時に=の有無がこんなところで大きな影響が出てしまうようですね。
    msなんてそうそう一致することないんじゃないの?って疑問も湧きますが、
    精度の荒いタイマーだと15ms程度のずれても同じ時間だと判定されたりするせいだということで納得しています。


    >Hebikuzureさん
    連投になってるんで、気づいたら不要なのを消しておいてくださいね。 
    子ウィンドウ自身のコンテンツとしてスクリプトが記述されていれば、focus できるようですね。
    そう思いますよねぇ。ところが、成功したことがないんです。
    何か特別な条件があるような気がしてなりません(例えば、window.onload時のみ.focus()が効くとか)
    まずは、再現しないと確認のしようがない状態です。誰か成功しましたか?

    試したのは、
    ①window.openで子ウィンドウを呼び出し、子ウィンドウ側のwindow.onload内でsetTimeout(function{window.focus()}, 10000);を仕掛けて、その間に、他ウィンドウをアクティブにしておく
    ②子ウィンドウ側にボタンを作り、ボタン押下(onclick)イベントでsetTimeout(function{window.focus()}, 10000);を仕掛けてその間に他のウィンドウをアクティブにしておく
    ③親ウィンドウ側で子ウィンドウのスクリプトの関数を呼び出し、その関数でwindow.focus()する
    ④③の最後のwindow.focus()をタイマー経由にする。
    上記すべてでfocus()は失敗しました。
    (上記は、タイマー値は200000が前提です)
    • 編集済み (´・ω・`) 2009年8月18日 21:02 focusが発動しない理由の補足
    2009年8月18日 14:22
  • 本件は、まだペンディング事項があると思いますが、
    ウィンドウズスクリプトプログラマさんの外部オブジェクトを使う、
    又は、(´・ω・`) さんのフォアグラウンドロックタイムアウト値を0にし、連続でfocusを呼ぶ
    という方向で行きたいと考えています。
    色々、ありがとうございました。

    2009年8月19日 11:07
  • 回答としてマークしたら、順番は可笑しくなりました。
    調整した方がいいかな
    2009年8月19日 11:14