ダイアログ間データ表示について

[戻る]
hiro 2005/05/06(金) 16:27:51
VC初心者です。
開発環境は WinXP SP1  VC++6.0 SP6  ダイアログベースです。

ダイアログA・ダイアログB・ダイアログCを作って
ダイアログAにはEditBoxとOKボタンを作成。
ダイアログBにはなにもなし。
ダイアログCにはEditBoxを作成。

ダイアログA:OKボタン押す
  ↓
ダイアログB
  ↓
ダイアログC:EditBoxにダイアログAに入れた値を表示。

下記のように関数を作成したのですが、
データの受け渡しは出来ているようなのですが、表示ができません。

ダイアログCのところで
SetDlgItemText
UpdateData
の2パターンと、
過去ログで見つけた、
ダイアログ間のデータのやりとりの方法
(リストボックスで試しました)
も試しましたが、
すべてDebug Assertion Failed! File:winocc.cpp
のエラーメッセージが表示されます。

根本的な間違いをしてるのでしょうか?
どなたかご教授ください。
よろしくお願いいたします。

void CDlgA::OnButton1() 
{    
    //エディットボックスの値を取得
    CString sText;
    CEdit* pEdit; //エディットボックスのメンバ変数
    
    pEdit = (CEdit*)GetDlgItem(IDC_EDIT1);//editBoxの内容を取得
    pEdit->GetWindowText(sText); 
    
    //--------------------------------------
    //DlgBのデータ受け渡し関数へ・・・
    //--------------------------------------
    CDlgB* pDlgB = new CDlgB();
    
    pDlgB->SendData(sText, nIndex, nFlag);
}

void CDlgB::SendData(CString sData, int nIndex, int nFlag)
{
    CDlgC* pDlgC = new CDlgC();
    pDlgC->SendData2(sData, nIndex, nFlag);
}

void CDlgC::SendData2(CString sData, int nIndex, int nFlag)
{    
SetDlgItemText(IDC_EDIT1,sData);
                    
    //UpdateData(TRUE);
    //m_Msg1 = sData;
    //UpdateData(FALSE);
}

WIZ [E-Mail] 2005/05/06(金) 17:57:31
ダイアログベースということなので、ダイアログ A はメインウィンドウですよね?
ダイアログ B と C はどのように表示しようとしているのでしょうか?

多分、ダイアログ A クラスの OK ボタンクリックのハンドラ(CDlgA::OnButton1 ?)で
ダイアログ B を表示するのだと思います。モーダルなら DoModal、モードレスなら
Create(ダイアログ B クラスのコンストラクタ内で呼んでいない場合) を呼び出す
必要があると思いますので、その辺のコードも省略せずに提示してください。
# この辺がはっきりすればもう少しアドバイスできます。

これは推論ですが、ダイアログ B と C のインスタンス生成後、DoModal or Create
していないのではないかと思います。このためウィンドウハンドルに結び付いていない
インスタンスに対して CWnd/CDialog クラスのメンバ関数を呼び出してアサーション
に掛かっているのではないかと思います。

iijima 2005/05/06(金) 18:04:22
ダイアログBとダイアログCについて、クラスのインスタンスをnew演算子で生成した後、
ウィンドウ(ダイアログボックス)を作成するための処理がないように見えます。
モーダルダイアログボックスならDoModalで、モードレスダイアログボックスならCreate
でダイアログボックスを作成するのが普通ですが、CDlgB, CDlgCクラスのコンストラク
タでダイアログボックス作成の処理を行うように定義したのでしょうか?
もうひとつ、new演算子で生成したインスタンスは、どこかでdelete演算子で削除しなく
てはいけませんが、それは大丈夫ですか?

iijima 2005/05/06(金) 18:07:23
おっと、かぶりました。
申し上げたいことはWIZさんと同じです。

hiro 2005/05/06(金) 22:40:42
WIZさん、iijimaさん、ありがとうございます。

ダイアログAはメインウインドウです。
ダイアログAを表示したと同時に
ダイアログB、Cをモードレス表示させています。
delete演算子で削除はしていませんでした。すみません・・・。
モードレス表示はここのサイトを参考にさせてもらいました。↓
http://www.athomejp.com/goldfish/mfc/dialog/modeless.asp

よろしくお願いします。

※ダイアログB、CのCreateのコードです。
BOOL CDlgB::Create(CWnd *pWnd)
{
  m_pParent = pWnd;
    BOOL bret = CDialog::Create(CDlgB::IDD, m_pParent);
    if( bret == TRUE)
    {
        this->ShowWindow(SW_SHOW);
    }
    return bret;
}

BOOL CDlgC::Create(CWnd *pWnd)
{
  m_pParent2 = pWnd;
    BOOL bret = CDialog::Create( CDlgC::IDD, m_pParent2);
    if( bret == TRUE)
    {
        this->ShowWindow(SW_SHOW);
    }
    return bret;
}

iijima 2005/05/06(金) 22:56:12
> ダイアログAを表示したと同時に
> ダイアログB、Cをモードレス表示させています。

そこで表示させたダイアログボックスと、最初に掲げられたコードでの処理にはどうい
う関係があるのでしょう?

hiro 2005/05/07(土) 00:36:54
説明不足ですみません。

1.ダイアログは3つとも、起動時に表示させたい。
2.ダイアログAのEditBoxで入力処理。
3.ダイアログBでは入力・表示はさせない。
 (AからCへの受け渡しのみで、コントロールのないダイアログが表示)
4.ダイアログCのEditBoxで、ダイアログAのEditBoxの
  値を表示させる。

2〜3はダイアログAのOKボタンを押したときの
処理です。
最初に書き込みしたコードがそれに当たります。

よろしくお願いいたします。

KING・王 2005/05/07(土) 02:11:02
1.を実現されるなら、最初に定時されたコードで記載されている、
>    CDlgB* pDlgB = new CDlgB();
の位置がまずいです。
ダイアログAの初期化処理なりて、ダイアログBをnewをして、されにpDlgB->Create()も必要
だと思います。

2.は単純にCDlgAの処理なので、省略します。

> 3.ダイアログBでは入力・表示はさせない。
ということんで、ダイアログBの存在意義がよく見えないのですが、
ダイアログCは、ダイアログBの初期化処理かなにかで、new、Createで作成されるということ
でしょうか?

その場合、4.を実現するのなら、
(1)ダイアログBのPublicなメンバに、CDlgB::SendData()を作成する。
(2)ダイアログCのPublicなメンバに、CDlgC::SendData()を作成する。
(3)ダイアログAでOKボタンの処理で、ダイアログAのEditBoxの値を取得する。
(4)続いて、OKボタンの処理で、取得した値を引数として、pDlgB->SendData()を実行す
る。
(5)CDlgB::SendData()の処理として、引数として受け取った値をさらに引数として、
pDlgC->SendData()を実行する。
(6)CDlgC::SendData()の処理として、引数として受け取った値を、ダイアログCのEditBox
に設定する。
というような感じだと思います。(少しまとめきれていないかもしれません)
ただし、ここで、pDlgBはCDlgAのメンバ変数としておき、(4)の処理以前に、new,Createに
より、
ダイアログBが作成されている必要があります。
また、pDlgCはCDlgBのメンバ変数としておき、(5)の処理以前に、new,Createにより、
ダイアログCが作成されている必要があります。

ダイアログCもダイアログAから直接作成しているのであれば、
完全にダイアログBを無視して、上記の(4)において、pDlgB->SendData()ではなく、
pDlgC->SendData()を実行し、その後(6)を行えばOKです。

長文で少し分かりにくくなってしまいました。ごめんなさい。

WIZ [E-Mail] 2005/05/07(土) 16:14:42
hiro さんが参考にしたサイトには確かに以下のコードが掲載されていますが、
少し危険だと思います。

    BOOL bret = CDialog::Create(CDlgB::IDD, m_pParent);
    if( bret == TRUE)

VC6 のヘルプを見ると、CDialog::Create は成功したら 0 以外、失敗したら 0
を返すと書かれており、「成功したら TRUE を返す」とは書かれていません。

    if (bret != 0)

とすべきでしょう。

また、hiro さんが参考にしたサイトにも掲載されている通り、ダイアログクラス
のインスタンスを new で生成した後、Create を呼び出さなければなりません。
# ダイアログ B/C クラスのコンストラクタの中から呼んでいるのなら別ですが。

ここから先は余談です。

CDialog::Create は非仮想関数なのでオーバライドできず、CDlgB/CDlgC クラスでの
定義はオーバロードになります。言い換えれば CDialog::Create と CDlgB::Create/
CDlgC::Create は何の関係もない関数ですが、たまたま同じ名前になっているという
ことです。
これは大変紛らわしく、もしインスタンスをポインタで指定する場合、そのポインタ
の型を誤って基本クラスの CDialog*/CWnd* 型にしてしまうと期待しない関数を呼んで
しまうことになります。

# 今回は引数の並びが違うので、コンパイルエラーになり気付けるでしょうが。

CDlgB::Create/CDlgC::Create は CDialog/CWnd のメンバ関数とは重複しない名前に
すべきです。

hiro 2005/05/07(土) 23:52:39
[[解決]]
KING・王さん、WIZ さん、iijimaさん、ありがとうございました。
解決いたしました。

newのあとにCreate、で出来ました。

KING・王さんのご質問ですが、
>ダイアログBの存在意義がよく見えないのですが、
>ダイアログCは、ダイアログBの初期化処理かなにかで、new、Createで作成されるとい
うこと
>でしょうか?
後々なのですが、ダイアログBには通過時のログのようなものを
表示させようと思っています。
ダイアログCはダイアログAの初期化処理で作成しています。

WIZさんご指摘の
    if( bret == TRUE)
に関してですが、
    if (bret != 0)
に変更致しました。
あと、関数名も変更致しました。
以後、気をつけたいと思います。

KING・王さん、WIZ さん、iijimaさん、
本当にありがとうございました。

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