質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

5514閲覧

外部アプリケーションの終了確認後の状況を取得したい

RyuL

総合スコア24

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/07/16 05:24

CreateProcessで起動した外部アプリケーションにて、このアプリケーションに終了メッセージを送信させた時に、そのアプリケーションが終了確認ダイアログで終了するかしないかの確認をする仕様だった場合の話です。

その時の現在のコードがこちらです。

c++

1case WM_CLOSE: 2 SendMessage( appHwnd, WM_CLOSE, 0, 0L ); // appHwnd:外部アプリケーションのハンドル 3 if( WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_OBJECT_0 ) // pi:外部アプリケーションのプロセス情報 4 { 5 CloseHandle( pi.hProcess ); 6 DefWindowProc( hWnd, message, wParam, lParam ); // hWnd:このアプリケーションのハンドル 7 } 8 9 break;

このコードを見てわかる通り、確認ダイアログで終了を選択した場合は問題ないのですが、終了をキャンセルした場合でもこちらのアプリケーションが終了してしまいます。

外部アプリケーションで終了をキャンセルした場合は、こちらのアプリケーションも終了をキャンセルしたいのですが、どの様にしたらいいのかご教授いただければ幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

すでに解決済みになっていますが、別の方法もあります。

外部アプリへのWM_CLOSE送信をSendMessage関数で行っているということは、関数から返ってきたときには外部アプリのWM_CLOSE処理は完了しているということになります。
WM_CLOSE処理では、通常DestroyWindow関数で自身を破棄するわけですが、確認が必要な場合はダイアログで選択させ、その結果終了させる場合はDestroyWindow関数を呼び、終了させない場合は何もしない、という流れになります(すべてのアプリがそうなっているとは言い切れませんが)。
つまり、確認ダイアログで終了を選んだ場合はSendMessage関数から制御が戻ってきた時点でウィンドウが破棄されていて、キャンセルされていたらまだウィンドウが存在する、ということになります。

要するに、SendMessage関数から戻ってきたときに外部アプリのウィンドウの存在確認をすれば、終了したか否かを判定できるということです。

ウィンドウの存在確認はIsWindow関数でできます。

投稿2018/07/17 02:18

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

単純に WM_CLOSE 内で待ち合わせなければ問題ないかと思います。定期的にプロセスの終了を監視するために WM_TIMER を使うと以下のようになります。

C++

1case WM_CREATE: 2 // WM_CREATE でなくても CreateProcess に成功した後で SetTimer すれば良い。 3 SetTimer( hWnd, 1, 200, NULL ); 4 break; 5 6case WM_CLOSE: 7 SendMessage( appHwnd, WM_CLOSE, 0, 0L ); 8 return 0; // DefWindowProc に渡さない。 9 10case WM_TIMER: 11 if( wParam == 1 ) 12 { 13 if( WaitForSingleObject( pi.hProcess, 0 ) == WAIT_OBJECT_0 ) // プロセスの終了をチェックするだけで待機しない。 14 { 15 CloseHandle( pi.hProcess ); 16 DestroyWindow( hWnd ); 17 } 18 } 19 break;

WM_TIMER を使うのが嫌ならメッセージループ側でプロセスの終了を待機しても良いかと思います。以下が例ですが、WM_CLOSE で終了要求を送信しても自アプリを終了しないようにするのは同じです。

C++

1// メッセージループ 2bool continueMessageLoop = true; 3while( continueMessageLoop ) 4{ 5 DWORD result = MsgWaitForMultipleObjects( 1, &pi.hProcess, FALSE, INFINITE, QS_ALLEVENTS ); 6 if( result == WAIT_OBJECT_0 ) 7 { 8 CloseHandle( pi.hProcess ); 9 DestroyWindow( hWnd ); // hWnd は WM_TIMER 時と同じもの 10 // pi.hProcess が常にシグナル状態となるので、プロセス終了後に MsgWaitForMultipleObjects 呼び出しが成立しない。 11 // WM_DESTROY で PostQuitMessage せずに終了した方が良い。 12 break; 13 } 14 else if( result == WAIT_OBJECT_0 + 1 ) 15 { 16 MSG msg; 17 while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) 18 { 19 switch( msg.message ) 20 { 21 case WM_QUIT: 22 // 多分、ここには来ない。 23 continueMessageLoop = false; 24 break; 25 default: 26 TranslateMessage( &msg ); 27 DispatchMessage( &msg ); 28 break; 29 } 30 } 31 } 32}

投稿2018/07/16 12:25

編集2018/07/16 13:30
atata0319

総合スコア881

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RyuL

2018/07/17 01:19

ご教授ありがとうございます。 教えて頂いた通りに書いたら問題なく解決しました。 WM_TIMERは他の処理で使っていたので、こちらの方法で解決しました。 また、よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問