ループ処理中止ダイアログについて

[戻る]
VC初心者 2008/09/15(月) 22:11:15
長いループ処理を開始した時に中止ダイアログを表示し、中止ボタンを押すとループ処
理を中止するプログラムを作成したいのですが、うまくいきません。
開発環境は、WinXP(SP2) VC++6.0 MFCです。

以下のような記述をしています。
ダイアログベース(CTestDlg)で作成しており、ボタンを押すとループ処理が始まると
同時に中止ダイアログ(Dialog1)が表示されます。
中止ダイアログの中止ボタン(Button2)を押すとループ処理が止まるようにしたいので
すが、Button2を押してもループ処理はとまらないし、中止ダイアログも閉じません。

根本的に間違っているようなのですが、行き詰っています。
どなたか、ご教授くださいますようお願いいたします。

TestDlg.hで
static BOOL bCancel;
を定義しています。

BOOL CTestDlg::OnInitDialog()
{
   CDialog::OnInitDialog();
   bCancel = FALSE;    
   return TRUE;  
}

void CTestDlg::OnButton1() 
{ 
   Dialog1* dlg1;
   dlg1 = new(Dialog1);
    
  dlg1->Create(IDD_DIALOG1, this);
   dlg1->ShowWindow(TRUE);
   dlg1->UpdateWindow();
    
   MSG msg;

   while(1){
      while(!bCancel && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
    if(!dlg1->IsDialogMessage(&msg)){
       TranslateMessage(&msg);
       DispatchMessage(&msg);
    }
      }

   // ループ処理
 
      if(bCancel){
         dlg->DestroyWindow();
    delete [] dlg1;
    break;
      }    
   }
}

void Dialog1::OnButton2() 
{
   bCancel = TRUE;
  
}

金魚ちゃん 2008/09/15(月) 22:22:19
bCancelの判定位置がおかしいかな。

void CTestDlg::OnButton1() 
{ 
 Dialog1* dlg1 = new(Dialog1);
 :
 for ( ; ; ){
  while ( PeekMessage(&msg,NULL,0,0,PM_REMOVE) ){
   :
  }
  if ( bCancel ){
   dlg->DestroyWindow();
   delete[] dlg1;
   break;
  }
  else{
   // ループ処理
  }
 }
}
これでどう。

VC初心者 2008/09/15(月) 23:14:40
金魚さん、ありがとうございます。
やってみましたが、ダメでした・・・

Dialog1のOnButton2では、bCancel=TRUEになっているのですが、CTestDlgの方で
bCancel=FALSEのままのようなんです。
bCancelの定義位置が違っているのでしょうか??

金魚ちゃん 2008/09/15(月) 23:18:29
PeekMessage関数の第2引数にダイアログのウインドウ・ハンドルを渡してないね。
ここを直したらどうなる?

ryo 2008/09/16(火) 01:24:39
>Dialog1のOnButton2では、bCancel=TRUEになっているのですが、CTestDlgの方で
>bCancel=FALSEのままのようなんです。
>bCancelの定義位置が違っているのでしょうか??
同名の別物になってる可能性が高そうですね

static BOOL bCancel;と同様の宣言は別にないか
bCancelはグローバルか、TestDlgのメンバ変数か
TestDlgとDialogの宣言・関数定義は、同一のファイルか、
それとも別ファイルか

このあたりどうでしょうか?

VC初心者 2008/09/16(火) 11:38:53
金魚ちゃんさん、ryoさんありがとうございます。
返信がおそくなり、申し訳ありません。

@h_cancelwnd = dlg1->GetSafeHwnd();
 として、PeekMessageの第2引数にh_cancelwndとしてみましたが、同じでした。

AbCancelの宣言は、testDlg.hに宣言しており、
 Dialog1.cppの頭でtestDlg.hをインクルードしています。
 testDlg.cppの頭でDialog1.hをインクルードしています。

BTestDlgとDialogの宣言・関数定義は、別ファイルです。

bCancelの宣言は以下の通りです。
何度もすみませんが、ご指導お願いいたします。


// testDlg.h : ヘッダー ファイル
//

#if !defined(AFX_TESTDLG_H__17F2C46D_575C_46AE_8A76_E198F3669C84__INCLUDED_)
#define AFX_TESTDLG_H__17F2C46D_575C_46AE_8A76_E198F3669C84__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////
// CTestDlg ダイアログ

static BOOL bCancel;

class CTestDlg : public CDialog
{
// 構築
public:
    CTestDlg(CWnd* pParent = NULL);    // 標準のコンストラクタ

---以下省略

bun 2008/09/16(火) 13:13:33
以下の話からして、
> AbCancelの宣言は、testDlg.hに宣言しており、
> Dialog1.cppの頭でtestDlg.hをインクルードしています。
> testDlg.cppの頭でDialog1.hをインクルードしています。

おそらく、
Dialog1.cpp から見た bCancel は、
testDlg.cpp から見た bCancel とは別物です。

同じものにするには、extern とか使いましょう。

PATIO 2008/09/16(火) 13:20:45
個人的には処理ループの中でメッセージループを回すのは
あまり好きでは無いので私だったら思い切ってマルチスレッドに
してしまいそうです。
メインスレッドとワーカースレッドのやり取りのやり方を
ちゃんと確立できれば、長い処理はワーカースレッド内で
完結して考えられるし、メインスレッドの方は普通にメッセージの
処理が出来るので整理はしやすいかなと。
マルチスレッドにすると複雑化すると言う事で避けるケースもある
見たいですけれど、私的には割りと簡単なケースでマルチスレッドに
慣れておくと応用しやすくなると思うので時間的に余裕があるなら
マルチスレッドにしてみるのも悪くないかもと思います。

マルチスレッドを強要するつもりは有りませんけれど、
こういう考え方もあるよと言う話です。

VC初心者 2008/09/16(火) 13:48:17
[[解決]]
bunさん、PATIOさん、ありがとうございます。
externを使って、できました。
基礎中の基礎ですね…すみません。勉強します。

マルチスレッドに関しては、まだ理解できていないのですが、
やり方としては、そちらの方がスムーズなんですよね。
今回は、何とか動きましたが、今後のためにネット等で調べてみます。

ありがとうございます。

古いスレッドには追加発言できません。