はじめまして
VC初心者で、質問させてください。
以下のようなことを実装しようと考えています。
1.自ウインドウで「OK」ボタンを押下した際に、自ウインドウに
メッセージを送信する。(PostMessage使用)
2.メッセージを受信した際に処理する関数(ON_MESSAGEのところに
設定した関数)で再度自ウインドウにメッセージを送信する。
(PostMessage使用)
3.上記2処理を100回(仮)繰り返す。
4.上記1〜3中はダイアログ(モードレス)を表示する。
5.100回(仮)メッセージ受信時処理を行ったらダイアログを
消去する。
ここで問題なのが、ダイアログ表示はできているのですが、
その処理中にダイアログにカーソルを当てると、時計マーク(処理中)
がでてしまいます。
これを解決するにはどのようにしたらよろしいのでしょうか?
プログレスバーのような処理でもしているのかな?
別スレッドにすれば良いかと。
メインスレッドとは別にワーカスレッドで処理してやれば良いです。
ご回答ありがとうございます。
実際には他プロセス(VC EXE)からメッセージ受信を何回も受けている間、
ダイアログを出したいのです。
結論はワーカスレッドでダイアログのCreateを行えばいいということでしょうか?
ちょっと、やりたいことのイメージが湧かないのですが、
要はメッセージを止めるからまずいので、Sleepしたりしてときどき
メッセージ処理をしてやれば、いいはず。
ちょっと時間がないので詳しくかけませんが、ググればサンプルが
見つかると思います。
逆です。
処理順は以下の通りです。
1.モードレスダイアログの表示
2.メッセージ受信時処理(複数回)
3.モードレスダイアログの消去
2の間に1で表示したダイアログが固まってしまうのです。
原因は2の処理が重いからだと思うのですが。
2の処理はできるだけ早く処理を行いたいのでSleepはさせたくありません。
ミスター一本釣りさん、はじめまして。
#「ROM」期間に、「一本釣り」されては
#目も当てられないので 、「ROM」でした。(^^
>ワーカスレッドでダイアログのCreate
↑は普通しないです。(GUIスレッドの使い方?かと)
2005/08/09(火) 10:44:29 で
「メッセージ受信時処理(複数回)」
普通は↑の処理をするため、ワーカスレッドを生成します。
つまり、ワーカスレッドの中で「メッセージ受信時処理」を
するのが、自然なプログラムだと思いますが・・・。
このように実装すると、ウィンドウが固まらない(筈)
1.プライマリスレッド(アプリが起動した直後に、必ず一つ存在)
で、モードレスを作成して下さい。
2.ワーカスレッドを生成し、そこで「受信時処理」をする
3.「受信時処理」が終われば、ワーカスレッドから
プライマリスレッドに知らせて、モードレス消去で良いのでは?
ワーカスレッドの意味・使い方、サンプルコードなら
RAPTさんも、案内しているように↓で
http://www.google.co.jp/
マルチスレッド、ワーカスレッドで検索。
MFCでも、Win32でも結構ヒットしました。
#あとは、地道に調べて、お好きな方法をどうぞ。
#ワーカスレッドの生成はそう難しくない(筈)
コードを提示して頂ければ、お手伝いができる方が
たくさん居そうなサイトだと思います。♪
すいません。
レスが遅くなりました。
現在以下のような感じでメッセージ受信処理(コールバック?)を
しています。
BEGIN_EVENTSINK_MAP(CXXXXXDlg, CDialog)
//{{AFX_EVENTSINK_MAP(CXXXXXDlg)
ON_EVENT(CXXXXXDlg, IDC_CTIXCTRL, 1, AAAAA, VTS_I4 VTS_I4)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()
エートリーぶさんがおっしゃているのはAAAAA関数内で
AfxBeginThreadをコールしてメッセージ受信時の実処理は別スレッドで
行うということでしょうか?
いまさらながらですけど
PeekMessageじゃ駄目なんでしょうか?
ループ中に
MSG msg;
if(PeekMessage((LPMSG)&msg,NULL,NULL,NULL,PM_REMOVE))
{
TranslateMessage((LPMSG)&msg);
DispatchMessage((LPMSG)&msg);
}
を入れたらってことです。
もちろんスレッドでもいいと思いますけど、
簡易的な処理はこれでも出来ると思うんですけど。
ただし、カーソルが時計マークにならないかどうかは正直分かりません。
全然はずしてたらごめんなさい。
ミスター一本釣りさん、まず環境を報告して下さい。
#MFCを使うようですが・・・
せっかく、リンクさんがコードを示してくれていますので
この方法も一案だと思います。直ぐに確認できそうなので。
だめなら、次ということで↓も考えませんか?
>AfxBeginThreadをコールしてメッセージ受信時の実処理は別スレッドで
悪い点というのは無さそうですが、とりあえずやって見て下さい。
それともう少し詳しいコードも示してください。
#ここの皆様の知恵も借りましょう。お願いします。
#他人には薦められない方法に固執していたことに気づきました。(汗
# > MSG msg;
# > (LPMSG)&msg,
# これって、不要な(毒にも薬にもならない)キャストでは?
# それと、UINTにNULLを渡すのは(C++ではNULL==0とはいえ)不適切では?
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpwinui/html/_win32_peekmessage.asp
確かにそうですね。
いいわけにはなりますが、どこかにあったプログラムからそのまま引用したものでした。
正確には
MSG msg;
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
ですかね。
メインスレッドでPeekMessageもしくはGetMessage関連を処理して、ワーカースレッドで処理を行うようにすればユーザーインターフェースが止まることはないと思います。
ちなみに、PeekMessageで処理するとほぼ確実にCPU使用率が100%になります。Sleepかなにかを入れてWindowsのシステムに処理時間を与えてやればCPU使用率は改善されます。
> MSG msg;
> if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
> {
> TranslateMessage(&msg);
> DispatchMessage(&msg);
> }
個人的には,
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
を推奨。一回に1メッセージでは,メッセージの処理が滞る可能性があります。
> ちなみに、PeekMessageで処理するとほぼ確実にCPU使用率が100%になります。
> Sleepかなにかを入れてWindowsのシステムに処理時間を与えてやればCPU使用率は改善されます。
やることがあるのですから,CPUの使用率が100%になるのは当たり前です。
# 根本的に,ワーカースレッドを使ったところで同じこと。
本来やるべきことがあるのに,強引に使用率を下げるのは改善ではなく改悪だと思いますが。
皆様色々ありがとうございました。
PeekMessageを使用することで
ダイアログが固まることはなくなりました。
おっしゃるとおりCPU使用率が100%になってしまいますが、
特に問題ないと思いますので、Sleepはいれないようにします。
→Sleepを入れるとThreadのSleep?なのでダイアログがその時
固まってしまうので。。。
わざわざワーカースレッドをあげるのであれば、メッセージポンプを
メインスレッド側に入れる必要は無いような気もします。
>実際には他プロセス(VC EXE)からメッセージ受信を何回も受けている間、
>ダイアログを出したいのです。
というところがいまひとつ判りません。
では、ダイアログが消えてよいタイミングはどうやって知るんでしょう?
出すのはメッセージが来たタイミングであるとして、
消えてよいと判断する基準は?
メッセージを受けた後の処理がどんな処理なのかわかりませんけれど、
考えるとしたら、ワーカースレッドに処理要求用のキューでも持たせておいて
メインスレッドは、ワーカースレッドが起動していない時は
処理中ダイアログでも出してワーカースレッドを起動し、キューに要求を積む。
ワーカースレッドはキューに要求がなくなるまで処理を続け、無くなったら自滅する。自滅する時にメインスレッドに終了通知を行ってから終わる。
メインスレッドはワーカースレッドからの終了通知を受けたら、
ワーカースレッドの終了待ちを行い、終了が確認できたらダイアログを消す。
実際にはもう少しタイミング調整がいると思いますが、ざっと書くとこんな具合でしょうか。
ワーカースレッドを上げるのであれば、ウインドウ関連の制御はメインスレッドに全てやらせるべきです。時間が掛かる処理をワーカースレッドに追い出す形ですね。
追加。
基本的にWindowsでのGUIを持つアプリのプログラミングは
一つの処理の中で長時間ループして抜けてこないような作りにするには
良くない設計だと思います。
特にウインドウメッセージから起動させる関数は出来る限り処理を速やかに
終わらせて関数を終了させ、制御をOSへ返すようにするのが基本でしょう。
その為にワーカースレッドがあるわけですからその辺を念頭において
アプリの設計を行う必要があると思います。
ツイート | ![]() |