[[20190110132036]] 『アプリケーションの前面表示』(ap) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『アプリケーションの前面表示』(ap)

 よろしくお願いします。

 会社で使うアプリがあり、4枚立ち上げまして、
 それを一気に前面表示させたいのですが、
 下記の[前面表示]〜[前面表示ふぉ]までの単体での実行だと
 必ず前面表示してくれるのですが、不思議なことに4つをまとめてCallさせると
 4枚のうち1〜3枚が表示されない(失敗する)ことが多々あります。

 ここでは以前ご教授頂いたSetForegroundWindow を使用していますが、
 AppActivateを使用しても同じような結果でした。

 最後の手段として単体で実行させるための4つのボタンを配置して、
 座標マクロなどでそれぞれクリックさせて
 一気に前面表示させているようにするしかないかなと考えておりますが、
 他の案などありますでしょうか?

 Private Function SetForegroundWindow _
    Lib "user32" (ByVal hWnd As Long) As Long
 Declare Function ShowWindow Lib "User32" (ByVal Hwnd As Long, _
    ByVal nCmdShow As Long) As Long
 Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

 Sub 前面表示()

 Dim ret

 ret = ShowWindow(3477314, 1)
 SetForegroundWindow 3477314

 End Sub

 Sub 前面表示つ()

 Dim ret

 ret = ShowWindow(2822042, 1)
 SetForegroundWindow 2822042

 End Sub

 Sub 前面表示すり()

 Dim ret

 ret = ShowWindow(11734968, 1)
 SetForegroundWindow 11734968

 End Sub

 Sub 前面表示ふぉ()

 Dim ret

 ret = ShowWindow(4001850, 1)
 SetForegroundWindow 4001850

 End Sub

 Sub 前面表示ALL()

 Call 前面表示
 Sleep 2000
 Call 前面表示つ
 Sleep 2000
 Call 前面表示すり
 Sleep 2000
 Call 前面表示ふぉ

 End Sub

< 使用 Excel:unknown、使用 OS:unknown >


環境を書いてもらわないとお話にならないのですが、WINDOWS APIの事だから、WINDOWSの事ですね。 バージョンによって動作が違うと思いますが、WIN7以降は特にそうなるでしょう。 WINDOWSは、表示更新をなるべく速くするため、同じようなメッセージが連続した場合、自動的に間引く処理が行われます。 だから結果が不安定なのでしょう。

対策としては、同時と判定されないくらい間を空ける事ですが、Sleep 2000 じゃ駄目でしょう。 2秒空けた!、と言いたいかと思いますが、Sleep命令はスレッドを握ったままになるのでCPUが解放されず、結局4つ出そろったときに一気に4つ分連続して要求されます。 なので、DoEvents を入れてCPUを開けてやることで、OSが動ける隙を作ってみてください。
(???) 2019/01/10(木) 14:06


 実行以前に
 >Private Function SetForegroundWindow _
 >   Lib "user32" (ByVal hWnd As Long) As Long
 ここでエラーにならないか?
 (Declareがない)

(ねむねむ) 2019/01/10(木) 14:10


???様 ありがとうございます。
windows7です。DoEventsを各Sleepの前に入れても、後に入れても、
やはり不安定な結果です。

ねむねむ様 失礼しました。
コピペしてきた時にいじってしまったと思われます。
元のプログラムは正常に動作します。
(ap) 2019/01/10(木) 14:27


DoEventsは、1回で変化が無いようならば、連続して2,3回ずつ入れてみてください。

また、1回ずつブレークポイントを設定した場合には、思った通りの動作になるのかと思いますが、いかがでしょうか?(1回ずつステップ実行でも前面にならないようだと、タスクバー表示されたアイコン点滅の影響とか、別の問題かも)
(???) 2019/01/10(木) 15:53


 ???様
 1回ずつブレークポイントを設定した場合には、思った通りの動作になります。
 ですが設定せず一気に実行しますとDoEventsを増やしてもやはり不安定になります。
 例えば他ウィンドウによって4枚とも隠れている状態で、2つ表示できて2つ失敗した場合、
 その失敗した2つのアイコンがタスクバーで点滅します。
(ap) 2019/01/10(木) 16:29

Sleep時間を10秒とかにしても変わらないでしょうか? そうなると、タスクバーに表示されたアイコンが点滅する機能と喧嘩しているのかもです。

4つのうち、3つまでにはフォーカスを与えないように起動して、4つ目だけ普通に起動する、というように変更できませんか?
(???) 2019/01/10(木) 17:07


発想を反転してみるというのはいかがでしょうか。

全面にあるウィンドウを全て最小化してしまえば良いのです!
(名無し) 2019/01/10(木) 17:57


 ???様
 Sleep時間を10秒にしても変わらず、代わりにタスクバーのアイコンが点滅するので喧嘩してると思われます。
 4つのうち3つまでにはフォーカスを与えないように起動して4つ目だけ普通に起動するとはどのようなことですか?
 3つはまとめてcallして残り一つは単体のSubで実行するということですか?
 それはやってみましたが、3つに減らしても2つに減らしても複数になった時点で結果はやはり不安定でした。

 名無し様
 ありがとうございます。自分だけであればその方法も有りなのですが、会社の他の従業員にも使用してもらう予定なので、
 それですと少し都合が悪いのです。
(ap) 2019/01/11(金) 12:59

3つ、というか全部でも構わないのですが、フォーカスを与えないよう、というのは、実際にはアプリ起動し、ウィンドウハンドルを得る、という部分のコードもあると思います。 起動する際、対象をアクティブにするかどうか指定できるはずなので、ここでアクティブにしないでおき、ShowWindowで初めてアクティブにしてみては?、という事です。 多分、変わらないとは思うのですけどね。

起動するアプリをメモ帳等に置き換えた、現象を再現できるシンプルなコードを提供できないでしょうか? 自分で書くにしても、APIだと時間がかかってしまうので避けたいし、現状と同じ起動方法とは限らないので。(ハンドルさえ正しければ、そこまでのコードはどう書いても良い、とも言えますが) APIの動作の話を、見もしないで想像だけでするのは無理があるようです。

別案として、SetWindowPos を利用して、一時的に最前面まで押し上げてしまう、というのはどうでしょうか?
(???) 2019/01/11(金) 15:45


 ???様
 SetWindowPosというものを存じてなかったので調べて試してみたところ、
 今のところ20回以上テストして全て成功できておりますので、
 もしかしたら解決出来た可能性が高いです。
 新たな問題が発生しましたらまた相談させて頂きます。
 助かりました!本当にありがとうございます。
(ap) 2019/01/12(土) 09:57

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.