Skip to content

MS_BringWindowToFront

nishi_74322014 edited this page Sep 1, 2026 · 1 revision

Windowを前面に出す

概要

「Window を前面に出す」方法については、
過去に似た問い合わせを何回も受けているため纏めておきます。

技術的背景については、「ウィンドウ・システム」を参照のこと。

詳細

SetForegroundWindow

ウィンドウの制御をプログラムから行う場合は、
SetForegroundWindow の Win32 API を使用できますが、
SetForegroundWindow を使用する場合、以下の様な条件があるようです。

移行メモ(欠落): 7 番目の条件の
「( 関数の SPI_GETFOREGROUNDLOCKTIMEOUT の説明を参照)」は
関数名が抜けていたため、SystemParametersInfo を補った。

補足(条件の意味): 上記 7 条件を一言でまとめると
**「今ユーザーが触っているアプリだけが、前面を奪ってよい」**という
設計思想である。
条件を満たさない場合、SetForegroundWindow
失敗する(FALSE を返す)のではなく、
タスクバーのボタンを点滅させるだけ
という挙動になる。
戻り値を見ても失敗が分からないことがあるため、
「呼んだのに前面に来ない」という問い合わせにつながりやすい。

AttachThreadInput

SetForegroundWindow でアクティブにならない場合には、

  • AttachThreadInput API 関数を呼び出した後に
  • BringWindowToTop API 関数を呼び出す。

参考

  • 【C#】アクティブでないアプリケーションの Form を
    アクティブ表示に変更したい - Insider.NET - @IT
    http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=32993&forum=7

    基本的にアクティブにした際(切り替え時)は、タスクバーが点滅するだけですが、
    このウインドウを、最前面に出すのは、以下のような処理が必要になります。
    
  • VB 初心者友の会 - Q&A 掲示板過去ログ
    2302-2 アプリケーションの切替方法について 井藤君@ビギナー
    http://www.gizcollabo.jp/vbtomo/log/archive/vbqanda_2302_2.html

    #2360-3 RE#2347: アプリケーションの切替方法について
    ■ゆー太郎 2001-12-03(月) 23:43

    > SetForegroundWindow を使うのが今までの手法だったのですが、Win98 から OS の
    > 動作が変わりました。タスクバー上で点滅するのみになります。
    >
    > これは「プログラムが勝手に、前面のウインドウを操作するのはおかしい。」という
    > 考えを元にしてます。なので、ご希望の動作は、「出来ない/してはならない」こと
    > になります。(-_-;)
    >
    
    それでも無理やり やりたいのであれば、AttachThreadInput API関数で
    無理やり現在アクティブなスレッドに自分のスレッドをアタッチして、
    その間にBringWindowToTop API関数で自分のフォームを前面に出します。
    その後もう一度AttachThreadInput API関数でデタッチして解除すれば可能です。
    もちろん、Windowsの仕様に反しますが。
    

移行メモ(誤字): 引用中の「現在アクティなブスレッド」は
「現在アクティブなスレッド」の誤りと解して修正した。

補足

この処理を「VIQ とローカル入出力の統合」と言う。

AttachThreadInput Win32 API で、VIQ を共有すれば、

当該プロセスが、

「そのプロセスが最後の入力イベントを受け取った。」

ということになり、

タスクバーを点滅させずに、ウインドウを最前面に出すことができる。

ただし、下記「Windows の標準仕様」のとおり
Windows 標準の操作性では無いため、
こちらも基本的にはあまり実装しない方が良い。

補足(副作用がある): AttachThreadInput
2 つのスレッドの入力キュー(VIQ)を統合するものなので、
アタッチしている間は
相手スレッドがハングすると自分も巻き込まれて固まる
また、フォーカスやキャプチャの状態が両スレッドで共有されるため、
予期しない挙動(キー入力が相手側に行く、など)を招きやすい。
「もちろん、Windows の仕様に反しますが」という上記の引用は、
単なる作法の問題ではなく実害を伴うという意味でも正しい。

プラットフォームによる差異

Vista 以降(SetWindowPos)

Vista 以降では SetWindowPos の Win32 API を使用できます。

Web からだと(ActiveX)

前述の Win32 API を使用する必要があるため、IE の場合、
ActiveX を使用する必要があります。JavaScript では実現不可能です。

補足(IE と ActiveX は終了した): Internet Explorer は
2022 年 6 月にサポート終了
し、Edge の IE モードも
2029 年までの経過措置である。
ActiveX を前提としたこの手法は現在使えない。
ブラウザからローカルのウィンドウを操作する必要がある場合は、
カスタム URL スキームでネイティブ アプリを起動する、
あるいは常駐アプリを立ててローカル HTTP / WebSocket で
指示を送る、といった構成に置き換わっている。

その他

常に最前面

起動時だけ最前面

Windows の標準仕様

マイクロソフトの出しているユーザーエクスペリエンスガイドライン

に、Z order に関する記述があります(P479)。

これによると「他のプロセスのウィンドウを変更するな。」とあります。
Windows 上のアプリケーションは、このガイドラインに従うべきであり、
Z order は触らない方がイイというコトになります。

補足(今なら通知で解決する): 「ユーザーに気付かせたい」という
元の要求に対しては、現在は
**トースト通知(Windows 通知センター)**を使うのが正解である
Microsoft.Toolkit.Uwp.Notifications など)。
ウィンドウを強引に前面に出す手法は、
全画面のプレゼンテーション中やゲーム中に割り込んでしまう、
入力を横取りして誤操作を招く、といった実害があるため、
本ページの「実装しない方が良い」という結論は現在も変わらない。
なお、タスクバーの点滅そのものは FlashWindowEx API で
明示的に行える。

参考


Tags: Windows, ウィンドウ・システム, プログラミング

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally