ダイアログ表示について


ミスター一本釣り  2005-08-02 01:19:16  No: 58476

はじめまして

VC初心者で、質問させてください。
以下のようなことを実装しようと考えています。

1.自ウインドウで「OK」ボタンを押下した際に、自ウインドウに
  メッセージを送信する。(PostMessage使用)
2.メッセージを受信した際に処理する関数(ON_MESSAGEのところに
  設定した関数)で再度自ウインドウにメッセージを送信する。
  (PostMessage使用)
3.上記2処理を100回(仮)繰り返す。
4.上記1〜3中はダイアログ(モードレス)を表示する。
5.100回(仮)メッセージ受信時処理を行ったらダイアログを
  消去する。

ここで問題なのが、ダイアログ表示はできているのですが、
その処理中にダイアログにカーソルを当てると、時計マーク(処理中)
がでてしまいます。
これを解決するにはどのようにしたらよろしいのでしょうか?


RAPT  2005-08-03 08:14:05  No: 58477

プログレスバーのような処理でもしているのかな?
別スレッドにすれば良いかと。
メインスレッドとは別にワーカスレッドで処理してやれば良いです。


ミスター一本釣り  2005-08-03 23:17:58  No: 58478

ご回答ありがとうございます。

実際には他プロセス(VC EXE)からメッセージ受信を何回も受けている間、
ダイアログを出したいのです。

結論はワーカスレッドでダイアログのCreateを行えばいいということでしょうか?


RAPT  2005-08-06 09:42:01  No: 58479

ちょっと、やりたいことのイメージが湧かないのですが、
要はメッセージを止めるからまずいので、Sleepしたりしてときどき
メッセージ処理をしてやれば、いいはず。

ちょっと時間がないので詳しくかけませんが、ググればサンプルが
見つかると思います。


ミスター一本釣り  2005-08-09 19:44:29  No: 58480

逆です。

処理順は以下の通りです。

1.モードレスダイアログの表示
2.メッセージ受信時処理(複数回)
3.モードレスダイアログの消去

2の間に1で表示したダイアログが固まってしまうのです。
原因は2の処理が重いからだと思うのですが。
2の処理はできるだけ早く処理を行いたいのでSleepはさせたくありません。


エートリーぶ  2005-08-09 23:47:30  No: 58481

ミスター一本釣りさん、はじめまして。
#「ROM」期間に、「一本釣り」されては
#目も当てられないので 、「ROM」でした。(^^

>ワーカスレッドでダイアログのCreate
↑は普通しないです。(GUIスレッドの使い方?かと)

2005/08/09(火) 10:44:29  で
「メッセージ受信時処理(複数回)」
普通は↑の処理をするため、ワーカスレッドを生成します。
つまり、ワーカスレッドの中で「メッセージ受信時処理」を
するのが、自然なプログラムだと思いますが・・・。
このように実装すると、ウィンドウが固まらない(筈)

1.プライマリスレッド(アプリが起動した直後に、必ず一つ存在)
    で、モードレスを作成して下さい。
2.ワーカスレッドを生成し、そこで「受信時処理」をする
3.「受信時処理」が終われば、ワーカスレッドから
  プライマリスレッドに知らせて、モードレス消去で良いのでは?

ワーカスレッドの意味・使い方、サンプルコードなら
RAPTさんも、案内しているように↓で
http://www.google.co.jp/
マルチスレッド、ワーカスレッドで検索。
MFCでも、Win32でも結構ヒットしました。
#あとは、地道に調べて、お好きな方法をどうぞ。
#ワーカスレッドの生成はそう難しくない(筈)

コードを提示して頂ければ、お手伝いができる方が
たくさん居そうなサイトだと思います。♪


ミスター一本釣り  2005-08-18 01:48:24  No: 58482

すいません。
レスが遅くなりました。

現在以下のような感じでメッセージ受信処理(コールバック?)を
しています。

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をコールしてメッセージ受信時の実処理は別スレッドで
行うということでしょうか?


リンク  2005-08-18 02:28:17  No: 58483

いまさらながらですけど
PeekMessageじゃ駄目なんでしょうか?
ループ中に
  MSG msg;
  if(PeekMessage((LPMSG)&msg,NULL,NULL,NULL,PM_REMOVE))
  {
    TranslateMessage((LPMSG)&msg);
    DispatchMessage((LPMSG)&msg);
  }

を入れたらってことです。

もちろんスレッドでもいいと思いますけど、
簡易的な処理はこれでも出来ると思うんですけど。
ただし、カーソルが時計マークにならないかどうかは正直分かりません。

全然はずしてたらごめんなさい。


エートリーぶ  2005-08-18 08:51:14  No: 58484

ミスター一本釣りさん、まず環境を報告して下さい。
#MFCを使うようですが・・・

せっかく、リンクさんがコードを示してくれていますので
この方法も一案だと思います。直ぐに確認できそうなので。

だめなら、次ということで↓も考えませんか?
>AfxBeginThreadをコールしてメッセージ受信時の実処理は別スレッドで

悪い点というのは無さそうですが、とりあえずやって見て下さい。
それともう少し詳しいコードも示してください。
#ここの皆様の知恵も借りましょう。お願いします。
#他人には薦められない方法に固執していたことに気づきました。(汗


RAPT  2005-08-18 10:13:20  No: 58485

# > MSG msg;
# > (LPMSG)&msg,
# これって、不要な(毒にも薬にもならない)キャストでは?


RAPT  2005-08-18 10:23:27  No: 58486

# それと、UINTにNULLを渡すのは(C++ではNULL==0とはいえ)不適切では?
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpwinui/html/_win32_peekmessage.asp


リンク  2005-08-18 10:55:49  No: 58487

確かにそうですね。
いいわけにはなりますが、どこかにあったプログラムからそのまま引用したものでした。
正確には

    MSG msg;
    if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

ですかね。


朱鷺  2005-08-18 17:26:12  No: 58488

メインスレッドでPeekMessageもしくはGetMessage関連を処理して、ワーカースレッドで処理を行うようにすればユーザーインターフェースが止まることはないと思います。
ちなみに、PeekMessageで処理するとほぼ確実にCPU使用率が100%になります。Sleepかなにかを入れてWindowsのシステムに処理時間を与えてやればCPU使用率は改善されます。


YuO  2005-08-18 20:18:37  No: 58489

> 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%になるのは当たり前です。
# 根本的に,ワーカースレッドを使ったところで同じこと。
本来やるべきことがあるのに,強引に使用率を下げるのは改善ではなく改悪だと思いますが。


ミスター一本釣り  2005-08-18 20:46:28  No: 58490

皆様色々ありがとうございました。
PeekMessageを使用することで
ダイアログが固まることはなくなりました。
おっしゃるとおりCPU使用率が100%になってしまいますが、
特に問題ないと思いますので、Sleepはいれないようにします。
→Sleepを入れるとThreadのSleep?なのでダイアログがその時
固まってしまうので。。。


PATIO  2005-08-18 20:56:58  No: 58491

わざわざワーカースレッドをあげるのであれば、メッセージポンプを
メインスレッド側に入れる必要は無いような気もします。

>実際には他プロセス(VC EXE)からメッセージ受信を何回も受けている間、
>ダイアログを出したいのです。
というところがいまひとつ判りません。
では、ダイアログが消えてよいタイミングはどうやって知るんでしょう?
出すのはメッセージが来たタイミングであるとして、
消えてよいと判断する基準は?
メッセージを受けた後の処理がどんな処理なのかわかりませんけれど、
考えるとしたら、ワーカースレッドに処理要求用のキューでも持たせておいて
メインスレッドは、ワーカースレッドが起動していない時は
処理中ダイアログでも出してワーカースレッドを起動し、キューに要求を積む。
ワーカースレッドはキューに要求がなくなるまで処理を続け、無くなったら自滅する。自滅する時にメインスレッドに終了通知を行ってから終わる。
メインスレッドはワーカースレッドからの終了通知を受けたら、
ワーカースレッドの終了待ちを行い、終了が確認できたらダイアログを消す。

実際にはもう少しタイミング調整がいると思いますが、ざっと書くとこんな具合でしょうか。
ワーカースレッドを上げるのであれば、ウインドウ関連の制御はメインスレッドに全てやらせるべきです。時間が掛かる処理をワーカースレッドに追い出す形ですね。


PATIO  2005-08-19 21:12:45  No: 58492

追加。
基本的にWindowsでのGUIを持つアプリのプログラミングは
一つの処理の中で長時間ループして抜けてこないような作りにするには
良くない設計だと思います。
特にウインドウメッセージから起動させる関数は出来る限り処理を速やかに
終わらせて関数を終了させ、制御をOSへ返すようにするのが基本でしょう。
その為にワーカースレッドがあるわけですからその辺を念頭において
アプリの設計を行う必要があると思います。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加