スレッドの停止・再開について(2)
メイン・ウインドウのクリエイト部で宣言、開始されるスレッド
(ハンドル=hThread1, ID=thread1_ID)を一つ持つプログラムがあります。
これを「スレッド1」として、
以下の条件の時にそのスレッド1を停止させたいのですが、
1.メインウインドウが非アクティブになった時。
2.メニュー、ポップアップメニュー、更にそれらからモーダルダイアログが
開かれた時。
(※つまるところ、"ユーザーがよそ事をしているときはスレッドを止める"ということ
ですが、)
(※スレッド1再開の条件は上の条件の裏返しです。)
まずスレッド1の停止の方法自体ですが、自分の以前のこの質問板での
「スレッドの停止・再開について」と同じもの(イグトランスさんにチェックを
して頂いたもの)で、スレッド1にメッセージをポストし、スレッドの流れを
待避線に引き込むというものです。
(但し必ずしもこの方法でないといけないということはありません。
SuspendThread/ResumeThreadのような強制中断でなければ
どんなやり方でも構いません。)
またその中で、条件1の「メインウインドウが非アクティブになった時。」について
書いています。
ここに表示されます。 [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
メイン・ウインドウのアクティベイト・イベントでスレッドに対して
スレッド停止・再開のメッセージを送り、
それをスレッドで拾って自らを停止・再開させます。
コード: 全て選択
'
'●ウインドウ・アクティブ/非アクティブ・イベント
'
Sub MainWnd_Activate(state As Integer, minimized As Integer)
If state=WA_INACTIVE Then
PostThreadMessage(thread1_ID, MYTHREADMSG_IDLE_THREAD, 0, 0)
Print "スレッド停止"
Else
PostThreadMessage(thread1_ID, MYTHREADMSG_RESUME_THREAD, 0, 0)
Print "スレッド再開"
End If
End Sub
として、そのポストされたメッセージをスレッド内で拾うために、
コード: 全て選択
While 1 'スレッドのループ用
ret=PeekMessage(msg,0,0,0,PM_REMOVE)
If ret=TRUE Then
Select Case msg.message
Case MYTHREADMSG_IDLE_THREAD
'----- スレッド停止ループ -----
' RESUME_THREADメッセージを受け取るまでここで待機ループ。
While msg.message<>MYTHREADMSG_RESUME_THREAD
ret=GetMessage(msg,0,0,0)
If ret=-1 Or ret=0 Then Exit Function
Wend
'----- スレッド停止ループ・終わり -----
そこで次に条件2「メニュー、ポップアップメニュー、更にそれらから
モーダルダイアログが開かれた時。」について以下のように書いてみたのですが、
メイン・ウインドウのウインドウメッセージループ内で、
コード: 全て選択
' ウィンドウメッセージを処理するためのコールバック関数
Function MainWndProc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord
' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。
Select Case dwMsg
Case WM_ENTERMENULOOP
PostThreadMessage(thread1_ID,MYTHREADMSG_IDLE_THREAD,0,0)
Case WM_EXITMENULOOP
PostThreadMessage(thread1_ID,MYTHREADMSG_RESUME_THREAD,0,0)
End Select
' イベントプロシージャの呼び出しを行います。
MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam)
End Function
このようにして、とりあえず「ポップアップメニューが開いた時に停止、閉じた時に再開」
としたのですが、このようにしていくとどうもうまく行かないと分かりました。
問題なのはまず、例えば"メニュー項目をクリックしてポップアップメニューを
開いた時、スレッド1はとりあえずきちんと停止するのですが、
そこからメインウインドウ以外の場所をクリックしてメインウインドウを非アクティブ
にします。そうすると、スレッド1は停止したままでいて欲しいのですが、実際には
"ポップアップが閉じた"としてスレッド1は再開してしまいます。
ポップアップを開く---->メインウインドウを非アクティブにする
スレッド1の状態(本来) 停止-------------------------------------------->
スレッド1の状態(実際) 停止--------------->再開 (ポップアップが閉じたため)
さらに"ポップアップメニューからの選択で更にモーダルダイアログが
開くような場合"、スレッドの停止状態としては、
「ポップアップが開いてからその後モーダルダイアログが
閉じるまでずっと停止していて欲しい」のですが、恐らくモーダルが開く直前に
ポップアップは「閉じる」訳でそのときにスレッド再開のメッセージが送られてしまい、
スレッド1は再開してしまうと思います。
モーダルが開く時に再びスレッド停止のメッセージを送るにしても、瞬間的には
スレッドが動いてしまうように思えますし、何より「何だかこのようにいちいちそれぞれの
GUIの状態ごとに停止、再開の処理を行うのは不自然だ」、と感じます。
冒頭の条件、
1.メインウインドウが非アクティブになった時。
2.メニュー、ポップアップメニュー、更にそれらからモーダルダイアログが開かれた時。
これらを満たせるようなスレッドの停止、再開の方法が
ありましたら是非教えて下さい。