DOBON.NET DOBON.NETプログラミング掲示板過去ログ

他のウィンドウの背後になったことを知る方法はありますか

環境/言語:[vb.net 2005 windowsXP]
分類:[.NET]

vb.net2005 XpSP3です
フォームがTopMost=Trueで作っているにもかかわらず何かの拍子にFirefoxとかエクスプローラーの後ろにもぐってしまいます
このようになった時に自分が最前面でなくなったことを知る方法はありますでしょうか
(その時にBringToFrontすればいいので)
■No32767に返信(/400さんの記事)
> vb.net2005 XpSP3です
> フォームがTopMost=Trueで作っているにもかかわらず何かの拍子にFirefoxとかエクスプローラーの後ろにもぐってしまいます
> このようになった時に自分が最前面でなくなったことを知る方法はありますでしょうか
> (その時にBringToFrontすればいいので)

フォーカスを失ったときではなく、「TopMost = True なのになぜか最前面でなくなった時」ですか?
正直、一筋縄でいく話ではなさそうに思います。

あまり良い例ではありませんが、タイマーで数秒おきに TopMost = True を実行すれば抑制はできると思います。

ただし、本当に使い勝手が良いのか?常に TopMost = True とすることでユーザの使い勝手を落としていないか、熟慮はしてください。
(前提などが見えないので、こちらでは判断がつかないため、余計なお世話になっているかもしれませんが)
返信ありがとうございます

> フォーカスを失ったときではなく、「TopMost = True なのになぜか最前面でなくなった時」ですか?
> 正直、一筋縄でいく話ではなさそうに思います。

今ふとエクスプローラーを立ち上げたら潜りました
但しもう一度立ち上げても潜りません
完全に再現するわけではありませんが再現性はあるかなと
で、一度エクスプローラーの下に潜ると画像のようにFireFoxの下にも潜るように
なります
(というか一度潜るとトレイアイコンクリックでBrigToFrontするまで二度と前面に
出てきません)

> あまり良い例ではありませんが、タイマーで数秒おきに TopMost = True を実行すれば抑制はできると思います。

それをやるとIME入力時など問題ありでした
なので前述のように手動BrigToFrontしているのですが面倒なので…

> ただし、本当に使い勝手が良いのか?常に TopMost = True とすることでユーザの使い勝手を落としていないか、熟慮はしてください。

今のところ2つのプログラム(どちらも自作)でなります
1つは画像の通り時計なので見えてないと意味ないですしもう一つも最前面でないと
意味が無いプログラムなのでその点は問題無いと思いますが
添付ファイル: ss.jpg (4 KB)
2014/12/14(Sun) 19:45:23 編集(投稿者)

■No32769に返信(/400さんの記事)
>>ただし、本当に使い勝手が良いのか?常に TopMost = True とすることでユーザの使い勝手を落としていないか、熟慮はしてください。
>
> 今のところ2つのプログラム(どちらも自作)でなります
> 1つは画像の通り時計なので見えてないと意味ないですしもう一つも最前面でないと
> 意味が無いプログラムなのでその点は問題無いと思いますが

たとえば同じ座標に重なるようなアプリが2つあったとき、お互いに最前面になろうと必死に動くと、無駄な動きになります。
IME で問題が出たと言うことですが、IME がそのプログラムと重なる位置にあったとき、無駄な動き(前に出ようとして出られなくてを繰り返す処理)をしないのでしょうか。

あなた自身しか使わないのであれば害はないかもしれませんが、そのような状況なのでしょうか。
(他のユーザも使うアプリなら熟慮が必要と書いたつもりなので、念のため、再度書いています)


なお、本当にこの手の通知を知るためには CBT フックが手となると予想されます。しかし、これ(グローバルフック)は VB.NET では使えません。
C++ などのネイティブコードを書ける環境で DLL を作ることが必要になります。

それ以外は Timer で監視するしかないでしょう。
WindowFromPoint を使えば、その点にどのウィンドウがあるかわかるでしょうから、そういう方面ですかね…。
>それをやるとIME入力時など問題ありでした

是非はわかりませんが、以下の方法ではいかがでしょう?

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.TopMost = True
End Sub

Private Sub Form1_Activated(sender As Object, e As EventArgs) Handles Me.Activated
Timer1.Enabled = False
End Sub

Private Sub Form1_Deactivate(sender As Object, e As EventArgs) Handles Me.Deactivate
Timer1.Enabled = True
Timer1.Interval = 5000
End Sub

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Me.TopMost = False
Me.TopMost = True
End Sub

DOBON.NET | プログラミング道 | プログラミング掲示板