- ベストアンサー
for文実行中を途中で中断するには?
質問させてください! 例えば作成したアプリケーションのウインドウ上に、ボタンAとボタンBがあります。 そしてそのボタンAを押した時(イベントAが起きたとき)に、 for文が10000回ループするというプログラムがあるとします。 しかし、その10000回ループしている過程でウインドウ上のBボタンを押した時(イベントBが発生)すぐに、そのループを中断してイベントBが起きたときに起こる別のプログラムを流したいのです。 現実は、10000回ループし終えるまで、ボタンBを押してもイベントBは起きることはありません。 10000回ループし終えてから、ボタンBを押した時に発生するイベントBが発生します。 for文のループをボタンBを押した時実行途中でも終了して、イベントA用に書いたプログラムを中断させ、その直後イベントBが起きた時用に書いたプログラムを流すようにしたいのですが、 プログラム初心者なものでよくわかりません。 どなたかご教授お願いいただけないでしょうか?!
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
★この場合はメッセージを処理します。 ・for 文のループの中で『ボタンB』を押すと WM_COMMAND などのメッセージがキューに入ります。 ・この情報を PeekMessage 関数で検査すれば for 文のループ途中でも強制終了可能な仕組みを組めます。 ・下に実装例を載せますので読み取って下さい。 ●実装例 static BOOL CALLBACK UserDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static BOOL swPushALoop; ←制御変数 switch ( uMsg ){ case WM_COMMAND: switch ( LOWORD(wParam) ){ case IDC_PUSH_A: FuncPushA( hDlg, &swPushALoop ); break; case IDC_PUSH_B: FuncPushB( hDlg, &swPushALoop ); break; default:return( FALSE ); } SetFocus( (HWND)lParam ); break; default:return( FALSE ); } return( TRUE ); } VOID FuncPushA( HWND hDlg, LPBOOL swLoop ) { MSG Msg; INT i; *swLoop = TRUE; ←初期化 for ( i = 0 ; (i < 10000) && *swLoop ; i++ ){ : ループ処理 : while ( PeekMessage(&Msg,hDlg,0,0,PM_REMOVE) ){ ←ここがポイント if ( !IsDialogMessage(hDlg,&Msg) ){ TranslateMessage( &Msg ); DispatchMessage( &Msg ); } } } } VOID FuncPushB( HWND hDlg, LPBOOL swLoop ) { *swLoop = FALSE; ←強制終了 Sleep( 0 ); ←念のため挿入(なくてもOKかもね) : ボタンBの処理 : } 解説: ・『ボタンA』のループ(処理中)に『PeekMessage』で常にメッセージがキューに入っているかを監視します。 ・そして、何かメッセージがあった場合は UserDialogProc プロシージャにそのメッセージを処理する指示を 『DispatchMessage』関数で送ります。 ・こうすると『ボタンB』が押されたときに WM_COMMAND メッセージがキューという場所に格納されますから 『DispatchMessage』関数により UserDialogProc プロシージャが呼び出され、WM_COMMAND メッセージの 『IDC_PUSH_B』を即処理します。 ・すると『FuncPushB』関数が実行されますが、この関数の最初で『swLoop』という変数に FALSE をセットする ので、ループ処理中の『FuncPushA』関数の『*swLoop』が FALSE になるので for 文を抜けます。 ・『IDC_PUSH_B』の先頭に『Sleep( 1 );』というウェイトを入れたのは『FuncPushB』関数が実行された後に 『FuncPushA』関数の for 文から抜けるまでの時間稼ぎで記述しなくても OK でしょう。 ・もしも、ループ処理を抜ける前に『ボタンBの処理』を開始出来ないのならば、安全の為に入れておきましょう。 ・以上。おわり。
その他の回答 (1)
- kargon21
- ベストアンサー率50% (1/2)
こんばんは。 他の方がC言語(?)で回答されているようなのでVBで回答してみます。 まず、for文の途中で他のイベントを受け取るには、 for文の処理中に一時的にWindowsに一瞬処理を返す必要があります。 これはDoEventsという命令をforループ内に追加することでできます。 次に処理を中断させる方法ですが、 グローバル変数で処理を抜けたかどうかを検査するための変数を用意し、 例えばこの変数がTrueの場合はBボタンがクリックされたとします。 コードは3つ追加する必要があります。 一つはforループ内(できれば最初の行)にこの変数の値をチェックする以下のような文を追加します。 (グローバル変数名をbolBClick(boolean)とします。) If bolBClick Then Exit For 次にBボタンがクリックされたときのイベント処理コードの先頭に次のコードを追加します。 bolBClick = True もうひとつ、同じイベント処理コードの最後に次のコードを追加します。 bolBClick = False 注意点として、各イベント処理のボリュームやタイミングによって若干処理が不安定になることも想定されるので、 シビアなタイミングを要求するような処理を実装されているのであればこの方法が使えないかもしれません。 必要であればループをDo文に変更してカウンタ変数を別途グローバル変数で用意し、 Bボタンクリック時の処理でカウンタを10000にしてしまうなどの工夫が必要かもしれません。
補足
迅速なご回答ありがとうございます! それなのにお返事が送れてしまい、真に申し訳ございません!!! 私の投稿した質問に書くのを忘れてしまいましたが、私はAPIでのプログラミングをおこなっております(謝) ですのでVBの方は・・・。 ですが、VBをやられている方たちは、kargon21様のご回答、絶対に役にたつとおもいます。 ご丁寧にご回答いただき、本当にありがとうございました!!
お礼
お返事が遅れてしまい、大変申し訳ございません! Oh-Orange様が教えていただいたことを、今までずっとあーでもない。こーでもないと私的に悪戦苦闘をしておりました。 そしてたった今・・・・、できることができましたぁ!!! とても感謝しております。 ご丁寧に教えていただき、本当にありがとうございました!!