-
Notifications
You must be signed in to change notification settings - Fork 0
MS_BringWindowToFront
- 戻る(ウィンドウ・システム)
- Windowを前面に出す
「Window を前面に出す」方法については、
過去に似た問い合わせを何回も受けているため纏めておきます。
技術的背景については、「ウィンドウ・システム」を参照のこと。
ウィンドウの制御をプログラムから行う場合は、
SetForegroundWindow の Win32 API を使用できますが、
SetForegroundWindow を使用する場合、以下の様な条件があるようです。
-
[WinSDK] ウィンドウを前面に出す方法 ヘニックスのライブ小屋
http://phoenix3430025.wordpress.com/2012/01/04/winsdk-%E3%82%A6%E3%82%A3%E3%83%B3%E3%83%89%E3%82%A6%E3%82%92%E5%89%8D%E9%9D%A2%E3%81%AB%E5%87%BA%E3%81%99%E6%96%B9%E6%B3%95/-
SetForegroundWindow 関数
https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setforegroundwindowMSDN によると、
- そのプロセスがフォアグラウンドプロセスである。
- そのプロセスはフォアグラウンドプロセスにより開始された。
- そのプロセスが最後の入力イベントを受け取った。
- フォアグラウンドプロセスがない。
- フォアグラウンドプロセスがデバッグ中である。
- フォアグラウンドがロックされていない
(LockSetForegroundWindow関数の説明を参照)。 - フォアグラウンドロックのタイムアウトが発生している
(SystemParametersInfo関数のSPI_GETFOREGROUNDLOCKTIMEOUTの
説明を参照)。
-
移行メモ(欠落): 7 番目の条件の
「( 関数の SPI_GETFOREGROUNDLOCKTIMEOUT の説明を参照)」は
関数名が抜けていたため、SystemParametersInfoを補った。
- SetForegroundWindow でアクティブにならない場合には?
http://hpcgi1.nifty.com/MADIA/VBBBS2/wwwlng.cgi?print+200402/04020031.txt
補足(条件の意味): 上記 7 条件を一言でまとめると
**「今ユーザーが触っているアプリだけが、前面を奪ってよい」**という
設計思想である。
条件を満たさない場合、SetForegroundWindowは
失敗する(FALSEを返す)のではなく、
タスクバーのボタンを点滅させるだけという挙動になる。
戻り値を見ても失敗が分からないことがあるため、
「呼んだのに前面に来ない」という問い合わせにつながりやすい。
SetForegroundWindow でアクティブにならない場合には、
-
AttachThreadInputAPI 関数を呼び出した後に -
BringWindowToTopAPI 関数を呼び出す。
-
【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 の Win32 API を使用できます。
-
winapi - How can I bring a window to the foreground in Vista using C++ -
Stack Overflow
http://stackoverflow.com/questions/534241/how-can-i-bring-a-window-to-the-foreground-in-vista-using-c -
ウィンドウのフォアグラウンド化 - cocoamix の日記
http://d.hatena.ne.jp/cocoamix/20090528/1243475334 -
Vista で Excel を最前面に表示
http://moosoft.jp/index.php?option=com_content&view=article&id=76&Itemid=106
前述の Win32 API を使用する必要があるため、IE の場合、
ActiveX を使用する必要があります。JavaScript では実現不可能です。
補足(IE と ActiveX は終了した): Internet Explorer は
2022 年 6 月にサポート終了し、Edge の IE モードも
2029 年までの経過措置である。
ActiveX を前提としたこの手法は現在使えない。
ブラウザからローカルのウィンドウを操作する必要がある場合は、
カスタム URL スキームでネイティブ アプリを起動する、
あるいは常駐アプリを立ててローカル HTTP / WebSocket で
指示を送る、といった構成に置き換わっている。
- フォームを常に最前面に表示させる
(タスクマネージャー, SetWindowPos, user32.dll, TopMost) - いろいろ備忘録日記
http://d.hatena.ne.jp/gsf_zero1/20100330/p1
-
@IT:.NET TIPS 多重起動禁止時に実行中の
Windows アプリケーションを最前面に表示するには? - C# VB.NET Windows フォーム
http://www.atmarkit.co.jp/fdotnet/dotnettips/151winshow/winshow.htmlただし、起動プロセスのウィンドウを使用して最前面化する必要があります。
マイクロソフトの出しているユーザーエクスペリエンスガイドライン
- Windows User Experience Interaction Guidelines
http://msdn.microsoft.com/en-us/library/aa511258.aspx
に、Z order に関する記述があります(P479)。
これによると「他のプロセスのウィンドウを変更するな。」とあります。
Windows 上のアプリケーションは、このガイドラインに従うべきであり、
Z order は触らない方がイイというコトになります。
補足(今なら通知で解決する): 「ユーザーに気付かせたい」という
元の要求に対しては、現在は
**トースト通知(Windows 通知センター)**を使うのが正解である
(Microsoft.Toolkit.Uwp.Notificationsなど)。
ウィンドウを強引に前面に出す手法は、
全画面のプレゼンテーション中やゲーム中に割り込んでしまう、
入力を横取りして誤操作を招く、といった実害があるため、
本ページの「実装しない方が良い」という結論は現在も変わらない。
なお、タスクバーの点滅そのものはFlashWindowExAPI で
明示的に行える。
- 本 Wiki 内
Tags: Windows, ウィンドウ・システム, プログラミング
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。