こんにちは。Konです。
PCはWinXP、MicrosoftVisualC++6.0 を使用しています。
MFC で、基本クラスをCFormView にしてプロジェクトを作りました。
子ウインドウを1つ追加してあり、基本クラスはCDialogです。
子ウインドウには、チェックボックスが1つあり、
オブジェクトIDをIDC_CHECK_test1としました。
最終的には、子ウインドウのチェックボックスの値を
親ウインドウのある関数に渡したいと思っています。
ところが、このチェックボックスの関数
void CXXXView::OnCHECK_test1()
が、いくらチェックを変化させても、呼ばれません。
色々調べてみたところ、
void CXXXView::DoDataExchange(CDataExchange* pDX) 等、
初期化に必要な関数が一度も呼ばれていないようです
これが原因なのでしょうか?
解決方法はお分かりになりませんか?
メッセージ・ハンドラは正しく設定されていますか?
正しいと思います。としか言えないのですが・・・。
ClassWizardでチェックボックスのIDを選択
BN_CLICKEDを選択して、関数の追加
という手順で関数を作りましたが、これでは不十分でしょうか?
話が見えないのですが、子ウインドウといっているのは、
CFormViewのリソースとして使っているものとは別の物ですか?
void CXXXView::OnCHECK_test1()と言う書き方をしているなら
これは、CFormViewにリソースとして使っているところのチェックボックスに対して
と言う意味だと思いますけれど。
CDialogの派生クラスで別に起こしたダイアログ上のチェックボックスの話を
しているのであれば、CXXXViewの関数にはならないと思いますよ。
CDialogの派生クラスにCXXXViewという名前をつけると言う話なら別ですが。
ダイアログ上のチェックボックスを弄ってもCFormView上のハンドラは呼ばれないと思い
ます。
CFormViewのリソースとして使っているものとは別の物です。
そういわれてみると、おかしな話ですね。
ダイアログの追加のとき、リソースの挿入からIDD_FORMVIEW
を選びました。そこに追加したチェックボックスから
上記のように関数を追加したら、CXXXViewになったんです。
IDD_FORMVIEWを選んだ理由は、親の基本クラスがCFormView
であるためで、子ウインドウでも同じ使い勝手が良いと思ったからです。
これが、マズかったのでしょうか?
そもそも、そのウインドウの持ち物で無いコントロールを制御する事は出来ません。
直接そのコントロールのインスタンスを参照する事が出来れば話は別ですが、
これは、既存のDDEやDDXの流れとはまったく別の話です。
とはいえ、オブジェクト指向的に考えるならCDialogの派生クラスの持ち物は
CDialogクラスの派生クラスに制御させるべきですし、イベントを直接受けるのも
そのウインドウであるべきです。親ウインドウに通知したいのであれば、
子ウインドウに親ウインドウのクラスのポインタを引き渡してそのポインタを通して
親ウインドウに設定するとか、ユーザ定義メッセージを使って親ウインドウに
通知するとか、子ウインドウと親ウインドウは独立して考えるべきでしょう。
ユーザー定義メッセージを使うとより疎結合な状態になるのでパーツとして利用しやすく
なります。
あと、同じリソースIDを選んだにしても
追加するクラスは選択できませんでしたっけ?
CFormViewで作成する限り、ハンドラ関数は呼ばれないでしょう。
だって、CFormView上のものとは別のコントロールを操作しているわけですから。
すみません、ついて行けていないようです。
>そのウインドウの持ち物で無いコントロールを制御する事は出来ません。
子ウインドウのチェックボックスが子ウインドウの持ち物として
成立していないと言うことでしょうか?
>CFormViewで作成する限り、ハンドラ関数は呼ばれないでしょう。
そもそも、子ウインドウをCFormViewで作るところがマズいということですか?
子ウインドウはCDialogの派生で、これにチェックボックスを配置していると
御自身が書いておられますよ。
同じIDのダイアログリソースを使っていてもウインドウが違う以上は
ウインドウのクラスとしては別物になります。
また、CDialogの派生クラスに張られているチェックボックスと
CFormViewの派生クラスに張られているチェックボックスは別物です。
CXXXView::OnCHECK_test1()はCFormView上のチェックボックスに操作を
行った時に呼び出されます。どんな操作を行ったときかは対応するウインドウメッセージに
寄りますので、書かれていない以上はわかりません。
CDialogの派生クラスに張られているチェックボックスに操作をした場合に
呼び出されるのは、CDialogの派生クラスのOnXXXXXXと言う関数になります。
CDialogの派生クラスに張られているチェックボックスをいくら操作しても
CXXXView::OnCHECK_test1()が呼び出される事は有りません。
ですから、
> そもそも、子ウインドウをCFormViewで作るところがマズいということですか?
子ウインドウはCFormViewでは無いのでしょう?
ならば、単純に考えても間違いだと思いますよ。
やりたい事がまだ整理できていないように思えます。
子ウインドウとCFormViewの派生のウインドウとの関係を整理した方が良いと思います。
もう一度確認しますが、
CDialogから派生した子ウインドウをchildとし、
CFormViewから派生したビューをparentとします。
1.childのダイアログリソースのIDは何ですか?
2.parentのダイアログリソースのIDは何ですか?
3.それぞれのダイアログリソースにチェックボックスは貼られていますか?
4.それぞれのチェックボックスのコントロールIDは何になっていますか?
すみません。いくつか勘違いしていたので、訂正します。
void CXXXView::OnCHECK_test1()
と書きましたが、これは、子ウインドウのクラス名が
CXXXViewだったためでした。
子ウインドウの基本クラスはCDialogでした。
申し訳ありません。
>1.childのダイアログリソースのIDは何ですか?
IDD_child です。
>2.parentのダイアログリソースのIDは何ですか?
IDD_parent です。
>3.それぞれのダイアログリソースにチェックボックスは貼られていますか?
貼られています。
>4.それぞれのチェックボックスのコントロールIDは何になっていますか?
子は、IDC_CHECK_test1 で、関数は CXXXView::OnCHECK_test1()
親は、IDC_CHECK_test2 で、関数は CYYYView::OnCHECK_test2() です。
お騒がせ致しました。
結局、親のリソース中のクラスの作成の記述が
myDialog = new CXXXView;
と書くべきところ、
myDialog = new CDialog;
となっていました。
参考にしたソースをコピペしたのが原因です。
本当に申し訳ありません。m(_ _)m
また、よろしくお願いいたします。