0

TopMostである必要があるWindowsフォームアプリケーションがあります。フォームをTopMostに設定しましたが、1つの場合を除いて、アプリケーションは希望どおりに機能します。

私のアプリケーションの上にポップアップする画面の一部にSWFムービーファイルを表示するサードパーティのアプリケーション(player.exeと呼ばれる)があります。

プロセスモニターを使用 して、私の場合、player.exeアプリケーションが呼び出すことを確認しました。
flash.exe <PositionX> <PositionY> <Width> <Height> <MovieFile>

flash.exe 901 96 379 261 somemovie.swf

フォームがTopMostに設定された後、flash.exeが新しいプロセスで生成されるため、アプリケーションの上に表示されます。

私が最初にしたことは、Flashが表示されないようにすることを期待して、アプリケーションでplayer.exeメインアプリケーションウィンドウを最小化することでした。しかし、残念ながら、そうではありません...フラッシュムービーが開始するたびにウィンドウが最小化されていても、ピクセル位置(901,96)に表示されます。次に、form.TopMostプロパティを10ミリ秒ごとにtrueに設定し続けるタイマーを作成してみました。この種の動作は動作しますが、swfファイルの非常に速いブリップが表示されます。

表示されている子プロセスをplayer.exeが生成するのを一時的に防ぐために使用できるWindowsAPI呼び出しの種類はありますか?私はそれが少し遠いように聞こえることを認めます。しかし、他の誰かが同様の問題を抱えているかどうか興味があります。


補遺:

この補遺は、以下のマシューの投稿に示されているいくつかの提案に対する回答を提供するためのものです。

コメントに記載されている緊急事態については、次のような解決策を検討します。

1)サードパーティアプリケーションは通常どのように開始および停止されますか?同じ方法で閉じることはできますか?それがサービスである場合、サービスコントロールマネージャーはそれを停止できます。通常のアプリケーションの場合は、エスケープキーストローク(おそらくSendInput()を使用)またはWM_CLOSEメッセージをメインウィンドウに送信すると機能する場合があります。

アプリを閉じる最も簡単な方法は、Ctrl-Alt-Delを押してから、プロセスを強制終了することです。-または-適切な方法は、マウスの左ボタンをクリックしながらESCを押したままにすることです...次に、ユーザー名とパスワードを入力し、いくつかのメニューをナビゲートしてプレーヤーを停止します。

PAUSEコマンドはありません...信じられないかもしれません。

アプリケーションを最小化しても効果がないため、WM_CLOSEを使用しても効果はないと思います。それはプロセスも殺しますか?そうでない場合は、どのように再開しますか。

2)うまく閉められない場合、殺してもいいですか?その場合、TerminateProcess()が機能するはずです。

2つの理由でプロセスを強制終了できません。1)再起動時に、ユーザー名/パスワードのクレデンシャルを指定する必要があります...マシンの再起動時にプロンプ​​トが表示されないため、これを回避する方法があるかもしれませんが... 2)タスクマネージャーでプロセスを強制終了するたびに正常に終了せず、エラーレポートを送信するかどうかを尋ねられます

3)どうしても他のプロセスを実行したままにする必要がある場合は、プログラムで高速ユーザー切り替えを呼び出して、別のセッション(競合する最上位ウィンドウがない)に移動できるかどうかを確認しようとします。APIのどこから始めればよいのかわかりません。(Peter Rudermanは、この目的のためにSwitchDesktop()を彼の回答で提案しています。)

私はこのアイデアに本当に興奮しました...多くのAPIラッパーメソッドを提供するCodeProjectでこの記事を見つけました。デスクトップを機能させるには、explorer.exeを実行する必要があると思うので(私は実行していません)、実装を停止しました。

EDIT2:考え直して...多分explorer.exeは必要ありません。試して報告します。

Edit3:その記事のコードを機能させることができませんでした。これをしばらく保留する必要があります。


回答の概要

予想通り、この問題に対する簡単な答えはありません。最善の解決策は、何も表示されないことを保証する必要があるときに、問題のある別のデスクトップに切り替えることです。動作するデスクトップスイッチングの単純なC#実装を見つけることができず、実装された後はまったく新しいワームのセットを開くだけになるのではないかという疑問が迫っていました。そのため、デスクトップスイッチングを実装しないことにしました。私はうまく機能するC++実装を見つけました。 他の人のために動作するC#仮想デスクトップの実装を投稿してください。

4

3 に答える 3

3

TopMostプロパティを設定する(またはWS_EX_TOPMOSTスタイルをウィンドウに追加する)と、システム内で一意になるわけではありません。任意の数のアプリケーションによって、任意の数の最上位ウィンドウを作成できます。唯一の保証は、すべての最上部のウィンドウがすべての非最上部のウィンドウの「上」に描画されることです。最上位のウィンドウが2つ以上ある場合でも、Zオーダーが適用されます。あなたの説明から、flash.exeも最上位のウィンドウを作成しているのではないかと思います。

定期的にウィンドウをZオーダーの一番上に強制することを除けば、できることはほとんどないと思います。ただし、このアプローチは危険であることに注意してください。2つ以上のウィンドウが同時にZオーダーの最上位に移動しようとすると、ユーザーがタスクマネージャーを使用して混乱する可能性があります。逃れる。

プログラムがコンピューター上の他のプロセスに干渉しようとしないことをお勧めします(タスクマネージャーのクローンなど、その明示的な目的でない限り)。コンピューターはユーザーのものであり、ユーザーはあなたのプログラムを他のすべてのプログラムよりも高く評価していない可能性があります。

補遺:

コメントに記載されている緊急事態については、次のような解決策を検討します。

  1. サードパーティアプリケーションは通常どのように開始および停止されますか?同じ方法で閉じることはできますか?それがサービスである場合、サービスコントロールマネージャーはそれを停止できます。通常のアプリケーションの場合は、エスケープキーストローク(おそらくSendInput()を使用)またはWM_CLOSEメッセージをメインウィンドウに送信すると機能する場合があります。

  2. うまく閉められない場合、殺してもいいですか?その場合、TerminateProcess()が機能するはずです。

  3. どうしても他のプロセスを実行したままにする必要がある場合は、プログラムで高速ユーザー切り替えを呼び出して、別のセッション(競合する最上位ウィンドウがない)に移動できるかどうかを確認しようとします。APIのどこから始めればよいのかわかりません。(Peter Rudermanは、この目的のためにSwitchDesktop()を彼の回答で提案しています。)

于 2009-07-15T19:07:44.023 に答える
0

Processクラスを使用してflash.exeを直接起動し、適切なProcessStartInfo設定を使用して、ウィンドウを非表示状態で表示するか、WindowStyleを非表示または最小化して表示することができます。

SetWindowsHookEx APIを使用してプロセス開始API呼び出しをインターセプトし、プロセスがflash.exeのときにコードを実行して、ウィンドウを最上位のステータスに復元することも検討できます。

于 2009-07-15T17:47:54.107 に答える
0

マシューの答えは素晴らしいですが、あなたが間違った質問をしているのではないかと思います。アプリケーションを最上位にする必要があるのはなぜですか?キオスクなどを作成しようとしている場合は、一番上が行く方法ではありません。

編集:マシューのコメントに対するあなたの回答を読んだ後、アラートを表示する前に、新しいデスクトップを作成してそれに切り替えることをお勧めします。(MSDNのCreateDesktopおよびSwitchDesktopを参照してください。)

于 2009-07-15T19:39:09.610 に答える