コントロール配列の作成方法

[戻る]
まま 2005/03/25(金) 15:54:11
VC++.net, Win2000Pro
VC初心者です。よろしくお願いいたします。

コントロール配列の作成方法について質問です。
http://www.asahi-net.or.jp/~uq7k-hrsm/vcdev2fr.htm#39

上記を参考に、以下のように設定しました。

■タブチャイルド画面A上にEditBoxを50個貼り付ける。
IDC_ED1 〜 IDC_ED50

■Aのクラスにpublicで宣言
    CEdit    m_Edit[ 50 ];

■Aのクラスにコンストラクタに宣言無し。
※

■Aクラス::DoDataExchange(CDataExchange* pDX)

    INT nIDEdit        = IDC_ED1;
    for( int i = 0; i < 50; i++)
    {
        DDX_Control(pDX, nIDEdit, m_Edit[i]);
        nIDEdit++;
    }


すると、

■別クラス(タブ親)のOnInitDialogに記載
int i = 0;//(仮)
    A.m_Edit[ i ].SetWindowText( "あああ" );

コンパイルはとおるのですが、ここでエラーが発生してしまいます。
エラーコードは0x4c224a1bなのですが、さっぱり解りません。


参考にしたページでは、
宣言は
CString m_Edit[50];

コンストラクタで
    INT nID        = IDC_ED1;
    for( int i = 0; i < 50; i++) 
    {
        m_Edit[i]    = _T("");
    }
                             
のようなことが行われていたのですが
CEdit m_Edit[50];でも必要なのでしょうか。

試しに画面上から"メンバ変数の追加"で変数を作成したときには
コンストラクタになにも出来なかったのでそのままにしたのですが・・。

              
コンストラクタに何か必要なのでしょうか。
それとも、どこをどのように直すべきでしょうか。

どうぞよろしくおねがいいたします。

dairygoods 2005/03/25(金) 16:11:58
A> ■Aクラス::DoDataExchange(CDataExchange* pDX)
B> ■別クラス(タブ親)のOnInitDialogに記載

これらの処理は、A->Bの順で実行されていますか?

通りすがり 2005/03/25(金) 17:38:56
IDC_ED1 〜 50 は 順番に番号が割り付けられていますか

まま 2005/03/27(日) 21:53:19
>通りすがり さん
はい。確認いたしました。
順番に割り付けられています。


>dairygoods さん

デバッグをしたところ、チャイルド画面の
DoDataExchange(CDataExchange* pDX)
の呼び出しがされていないことがわかりました。

これは、自分でよびださなければならないものなのでしょうか。
少し探したのですが、いまいちよく解かりません。

無知で申し訳ありません、
お手数ですが、ご教授いただけないでしょうか。

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

reshia 2005/03/27(日) 22:10:42
実際に作ってみました。XP+VS.NET2003です。
プロジェクト:MFC
形式:ダイアログ
でウィザードを完了(プロジェクト名は「Sample」)

(1)エディットボックスを20個貼り付ける(Ctrl+ドラッグで簡単操作)
(2)ソリューションエクスプローラでResource.hを開いてIDC_EDIT1〜IDC_EDIT20が1000〜
1019で#defineされているのを確認
(3)SampleDlg.hに「CEdit m_edit[20];」を追加
(4)DoDataExchange(CDataExchange* pDX)を次のように書き換え
-------------------------------------
void CSampleDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);

    // ソリューションビューからResource.hを参考に
    int nIDC = IDC_EDIT1;
    for (int i=0; i < 20; i++) {
        DDX_Control(pDX, nIDC+i, m_editArray[i]);
    }
}
-------------------------------------
(5)動作の確認のために「Test」ボタンをダイアログに貼り付ける(IDC_TEST)
(6)「Test」ボタンを押したら飛んでくる関数をCSampleDlgプロパティから追加
(7)以下のようにコーディング
-------------------------------------
void CSampleDlg::OnBnClickedTest()
{
    // TODO : ここにコントロール通知ハンドラ コードを追加します。
    CString buf;
    for (int i=0; i<20; i++) {
        buf.Format("%04d", i);
        m_editArray[i].SetWindowText(buf);
    }
}
-------------------------------------
(8)実行結果を確認
以上です。これでエディットボックスに順番に0000-0019の数字が書き込まれたのを確認
しました。

何か問題があれば、また。

reshia 2005/03/27(日) 22:12:26
すみません、間違えてますね。
m_editArray→m_edit

まま 2005/03/28(月) 00:49:39
>reshia さん

大変ご親切ご丁寧にご教授いただき、感謝しております!
どうもありがとうございます。

お教えいただいたとおり、
(1)〜(4)を行ったのですが、
(4)DoDataExchange(CDataExchange* pDX)
のfor文で、24回まわしているのですが、
12回目で以下のようなエラーが発生してしまいます。
----------------------------------
Debug Assertion Failed!

0x7c248ece(mfc70d.dll)でハンドルされていない例外が発生しました。
ユーザー設定のブレークポイント
----------------------------------

実は、画面上には
EditBoxA が24個
EditBoxB が24個
RadioBoxA が24個
RadioBoxB が24個
RadioBoxC が24個
RadioBoxD が24個
GroupBox が24個
ありまして、これらをfor文でまわしております。
これらのIDC_XXXはそれぞれ連番で、全てのIDで重複はありません。


もしかしてこれらの数が問題になっていたりするのでしょうか?
画面上のコンポーネントは最大数256と聞いたので、一応その範囲内かとは
思うのですが。。。
違っていたら申し訳ありません。


原因が思い至らなくお手数をお掛けいたします。
どうぞよろしくお願いいたします。

まま 2005/03/28(月) 00:52:47
>dairygoods さん

遅くなりました。
DoDataExchange(CDataExchange* pDX)
には飛べるようになりました。
チャイルドのタブ画面の基本クラスがCDialogになっていなかったのが
原因のようでした。

ありがとうございました。

まま 2005/03/28(月) 14:54:33
「まま 2005/03/28(月) 00:49:39 」の補足です。
                                             
リソースIDの重複なしを確認し、ためしに違う値にしてやっても
12回目のループで落ちてしまいます。

HWND CDataExchange::PrepareCtrl(int nIDC){}関数に
nIC = 1029で入り込み、

m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);
ここで(hWndCtrl == NULL)、

// Could be a windowless OCX
pSite = m_pDlgWnd->GetOleControlSite(nIDC);

と進んでいき、pSite=NULLで落ちます。

これはどのように対処したらよいのでしょうか。

無知で申し訳ありません
ご教授よろしくお願いいたします。

dairygoods 2005/03/28(月) 16:13:31
その1029番のコントロールは実際に存在するんでしょうか?

まま 2005/03/28(月) 16:57:15
>dairygoods さん

はい。
試しにfor文内にある
EditBoxA 
EditBoxB 
RadioBoxA
RadioBoxB
RadioBoxC
RadioBoxD

のエラー発生するコントロールの処理をコメントアウトしたところ、
他のコントロールで発生いたします。

もうひとつ試しに、いっそのことはじめから作成して見たのですが、
同じように12回目で発生いたします。

困りました・・。

まま 2005/03/28(月) 18:39:25
[[解決]]
解決いたしました。

void CTabToday::DoDataExchange(CDataExchange* pDX)
    INT nIDEdit      = IDC_EDIT1;
    for ( int i = 0; i < 24; i++)
    {
        DDX_Text(pDX, nIDEdit+i,   m_Edit[i]);
    }

としておりました。
    DDX_Text(pDX, nIDEdit,   m_Edit[i]);

と直し、正常に動くことを確認いたしました。
ちょうど半分の12回でエラーが起こっていたようです。
全く気づきませんでした。

ご指摘感謝しております。

有難うございました。

Ban 2005/03/28(月) 19:04:09
で、Belution の方に報告はないのですか。

超初心者 2005/03/28(月) 21:16:27
まったくひどい話だよ。

Belution だけじゃなくてメーリングリストにも発言している。

上記の発言では、どうしてエラーが起きたのか、
どうやって解決したのか、
この掲示板を何度読み返しても、わからない人も多いと思う。
当然だわかるわけない。
さすがマルチする人だけあってフォローは手抜きだ。

↓以下のように書いていたから
for ( int i = 0; i < 24; i++)
{
    DDX_Text(pDX, nIDRadD+i,    m_RadioD[i]);
    nIDRadD++;
}

↓以下のように書いて解決した。
for ( int i = 0; i < 24; i++)
{
    DDX_Text(pDX, nIDRadD,    m_RadioD[i]);
    nIDRadD++;
}

ということだ。

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