|
■No44708 (kashi さん) に返信 > >>WaitForSingleObject の使い方の応用ですが、タイムアウト時間に 0 を指定することで、対象プロセスが実行中か否かを即座に調べることができます。 > >>WAIT_TIMEOUT_0 が返れば実行中です。 > >>GetExitCodeProcess よりきれいな方法だと思います。 >> >>あるいは、MsgWaitForMultipleObjectsEx を使った方がいいのかも。 > > なるほど・・・なんとなくイメージが掴めました。 > ここにぶら下げておくかな。二重起動についてはとりあえず除外...
どのパターンでやる場合でも... ボタンハンドラの最初で 親画面EXEのメインウィンドウを無効化する(AfxGetMainWnd()->EnableWindow(FALSE)など)*1 子画面EXEを起動する(CreateProcessなど)*2
1.タイマーピークする場合 SetTimer でタイマーを発動する(0.2秒〜0.5秒くらいの間隔で呼び出す)<ウィンドウは何でもよい タイマーハンドラでは GetExitCodeProcess で戻り値を取得する(STILL_ACTIVEなら実行中)*2のプロセスハンドルを対象とする 処理が終わっていたら、タイマーを終了し、親画面のメインウィンドウ(*1)をEnableWindow(TRUE)する 戻り値は一切必要ないのであれば WaitForSingleObject(...,0) == WAIT_TIMEOUT でも問題ありません。
2.MsgWaitForMultipleObjects の場合 MsgWaitForMutipleObjects( 1, &(*2のハンドル), FALSE, INFINITE, QS_ALLEVENTS );を行う。 WAIT_OBJECT_0+1 なら、何かメッセージが来たとして メッセージが来た場合は、メッセージが空になるまでメッセージポンプを回す(MFCなら、while(PeekMessage(...,PM_NOREMOVE)){ theApp.PumpMessage()}) 戻り値が、WAIT_OBJECT_0 なら、子画面終了なので、ループを抜けクローズ処理をする(1と段取り的にはほぼ同じ) EXEが終了してなければ、MsgWaitFor... に戻る
と、こんな感じです。 1の場合、今までの処理とは異なり複数のメッセージに分断されるためちょっと面倒かもしれません。 2の場合は、現在 WaitForSingleObject になっている部分を MsgWaitForMultipleObjects のループに変える形になります(関数に切り出してもいいです)。 処理的には2のほうが変更箇所の範囲も波及エリアも少ないです。 が、ここに書いてある情報+MSDNライブラリでコーディングできないようなら1で作成することをお勧めします。
どちらの場合も、重要なポイントは、親画面のメインウィンドウ(モーダルダイアログから呼ばれているのならそのモーダルダイアログのウィンドウ)を EnableWindow( FALSE )として、無効化しておくことです。 これを行うことにより、メニューや終了コマンドなど一切受け付けなくなります(ダイアログ内の全部の子コントロール類も含む)。
|